Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 8 октября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Программисты долго мучаются с кодом прогаммы, изучают С++, WinAPI функции, MSDN. Потом пишут банальную систему защиты или навешивают банальный протектор, а крэкеры и реверсеры справляются с такой защитой за 5 минут. В итоге, продажи программы почти нулевые. Чтобы такого не допустить, тут самому надо немного поднабрать опыта отладки, реверсинга, тот же отладчик Ollydbg изучить или дизассемблер IDA Pro. Но где искать по крохам эти знания? Нет, конечно можно годами "методом тыка" разбираться, но куда быстрее видеокурс специальный посмотреть. Вот тут он есть: ссылка. Автор курса с большим опытом и объясняет понятно, я из этого курса много узнал про то как работает компьютер, процессор, про инструменты специальные и как с ними работать. Мои коллеги программисты на работе ничего такого и не знают, теперь я им нос утру.

Механизм обработки сетевых событий в Winsock2


Автор: Joseph Dempsey

Обычно, при программировании сокетов под Winsock 1.1, используются стандартные и, надеюсь известные большинству программистов операторы. При этом оповещение о событии на сокете проходит через сообщения windows. Думаю, не секрет, что такой способ порождает массу проблем при разработке приложений. Однако можно воспользоваться другим методом - в обход сообщений Windows, а именно через события WSA (WSA Events).

Как это работает?

При работе с сокетом большинство программистов используют стандартный набор событий: для отправки данных, приёма данных, соединения с другим сокетом, для установления канала передачи данных при входящем запросе и для закрытия сокета. Возможно есть и другие события для сокетов, но в этой статье мы сосредоточимся на основных. Когда одно из этих событий, ассоциированных с сокетом, происходит, то мы получаем сигнал и производим необходимые действия для обработки данного события.

Вот основные константы, описывающие сетевые события (те, которые будут фигурировать в данной статье):

FD_ACCEPT
FD_READ
FD_WRITE
FD_CLOSE
FD_CONNECT

Итак, давайте рассмотрим весь процесс создания, отслеживания и обработки сетевых событий.

Во-первых нам прийдётся инициализировать библиотеку winsock2. Впринципе существует нескольколько способов сделать это, например так:

WSADATA wsd;
 LPFN_WSASTARTUP lpf = (LPFN_WSA_STARTUP)::GetProcAddress( ::LoadLibrary("WS2_32.DLL"),
                                                              "WSAStartup");
 lpf(0x0202, &wsd);
 

Инициализировать можно в любом месте программы, но обязательно до вызова каких-либо функций winsock. Следующий важный момент - это создание события, которое мы хотим отслеживать на данном сокете. Для этого будем использовать вызов Winsock2 API  ::WSACreateEvent(); После того, как событие создано, его нужно связать с сокетом, события которого мы хотим контролировать и обрабатывать. Это делается функцией WSAEventSelect(...).  Следующий пример показывает, как отследить событие, сигнализирующее о том, что на сокет пришёл запрос на установление канала связи. Обычно такую операцию можно проделывать на прослушивающем (listening) сокете.  В примере это SOCKET m_listen . Итак, как это выглядит:: 

WSAEVENT hEvent = WSA_INVALID_EVENT;
 hEvent = WSACreateEvent();
 ::WSAEventSelect(m_listen, m_hEvent, FD_ACCEPT);
 

Если мы хотим, чтобы сокет (в данном случае это SOCKET m_socket ) информировал нас о том, что готов принять или передать данные, то событие создаётся следующим образом:

WSAEVENT hDataEvent = WSA_INVALID_EVENT;
 hDataEvent = WSACreateEvent();
 ::WSAEventSelect(m_socket, hDataEvent, FD_WRITE | FD_READ | FD_CLOSE);
 

Необходимо заметить, что для одного и того же сокета невозможно создать два объекта событий, то есть следующий код неверен:

WSAEVENT hEvent1 = WSA_INVALID_EVENT;
 WSAEVENT hEvent2 = WSA_INVALID_EVENT;
 
 hEvent1 = WSACreateEvent();
 hEvent2 = WSACreateEvent();
 
 ::WSAEventSelect(m_socket, hEvent1, FD_READ);
 ::WSAEventSelect(m_socket, hEvent2, FD_WRITE);
 

 

Обработка уведомлений о событиях

Теперь, когда события заданы, нам необходимо ожидать их и, соответственно, обрабатывать. Для ожидания событий можно использовать функцию WSAWaitForMultipleEvents(...). Эта функция будет работать как поток в спящем режиме до тех пор, пока не произойдёт событие, на которое мы хотели бы отреагировать. Давайте посмотрим на пример вызова этой функции:

// m_listen  и  m_data два существующих сокета:
 WSAEVENT hEvent1 = WSACreateEvent();
 WSAEVENT hEvent2 = WSACreateEvent();
 
 ::WSAEventSelect(m_listen, hEvent1,  FD_ACCEPT);
 ::WSAEventSelect(m_data,   hEvent2,  FD_READ | FD_CLOSE);
 
 WSAEVENT* pEvents = (WSAEVENT*)::calloc(2, WSAEVENT);
 pEvents[0] = hEvent1;
 pEvents[1] = hEvent2;
 
 int nReturnCode = ::WSAWaitForMultipleEvents(2, pEvents, FALSE, INFINITE, FALSE);
 

Если же мы хотим ожидать только одного события, то эту функцию можно вызвать следующим образом:

 int nReturnCode = ::WSAWaitForMultipleEvents(1, &hEvent1, FALSE, INFINITE, FALSE); 

Первый параметр - это количество событий, которые мы хотим ожидать. Второй параметр - это указатель на массив событий, которые мы хотим ожидать. Третий параметр имеет значение BOOL, которое определяет - будет ли функция оставаться в спящем режиме до тех пор пока не сработают все события. Обычно этот параметр задаётся как false, но возможно Вам может понадобиться ожидать наступления всех событий. Четвёртый параметр определяет - как долго ожидать наступления события. Обычно я запускаю отдельный поток и оставляю его как infinite. Но, если Вы будете запускать функцию в основном потоке, то может понадобиться поставить ограничение в 5 (или больше) секунд, чтобы дать возможность приложению обрабатывать другие события. Пятый параметр указывает на то, хотим мы или нет получать алерты.

Теперь необходимо позаботиться об обработчиках каждого события. Перво-наперво нам необходимо получить достоверную информацию о том, какое событие возникло. Для этого существует функция ::WSAEnumNetworkEvents(...). Один из параметров которой - это структура под названием WSANETWORKEVENTS. Принимая во внимание код, приведённый выше, получим следующее:

WSANETWORKEVENTS hConnectEvent;
 WSANETWORKEVENTS hProcessEvent;
 
 ::WSAEnumNetworkEvents(m_listen, hConnectEvent, &wsaConnectEvents);
 ::WSAEnumNetworkEvents(m_data,   hProcessEvent, &wsaProcessEvents);
 

В заключении мы получаем событие, которое возникает на одном из сокетов. Давайте посмотрим, как выглядит процесс выборки нужного события и его обработки:

if( (wsaConnectEvents.lNetworkEvents & FD_ACCEPT) &&	//Нужное ли нам событие ?
    (wsaConnectEvents.iErrorCode[FD_ACCEPT_BIT] == 0) )	//если нет ошибок,
    {                                                    //то обрабатываем
 	/*
 		....
 		Здесь находится обработчик
 		....
 	*/
    }
 

Эта проверка может быть сделана для каждого WSAEVENT, который Вы установили, и для каждого сетевого события, для которого WSAEVENT будет сигнализировать. Для обработки другого события, в последнем примере достаточно изменить FD_ACCEPT на необходимую константу и, соотвественно изменить константу проверки бита ошибки.





<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS