Программирование на C++ глазами хакера



             

Алгоритм приема/передачи данных


В разд. 4.10.2 мы уже рассмотрели пример, в котором сервер асинхронно ожидает соединения с помощью функции select, и как только происходило подключение, создавался новый поток, который обменивался данными с клиентом. Самое узкое место в этом примере — второй поток, который работал только с одним клиентом.

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

Листинг 6.1. Алгоритм асинхронной работы с клиентом
DWORD WINAPI NetThread(LPVOID lpParam) { SOCKET sServerListen; SOCKET ClientSockets[50]; int TotalSocket=0;

struct sockaddr_in localaddr, clientaddr; int iSize;

sServerListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if (sServerListen == SOCKET_ERROR) { MessageBox(0, "Can't load WinSock", "Error", 0); return 0; }

ULONG ulBlock; ulBlock = 1; if (ioctlsocket(sServerListen, FIONBIO, &ulBlock) == SOCKET_ERROR) { return 0; }

localaddr.sin_addr.s_addr = htonl(INADDR_ANY); localaddr.sin_family = AF_INET; localaddr.sin_port = htons(5050);

if (bind(sServerListen, (struct sockaddr *)&localaddr, sizeof(localaddr)) == SOCKET_ERROR) { MessageBox(0, "Can't bind", "Error", 0); return 1; }

MessageBox(0, "Bind OK", "Error", 0);

listen(sServerListen, 4);

MessageBox(0, "Listen OK", "Error", 0);

FD_SET ReadSet; int ReadySock;

while (1) { FD_ZERO(&ReadSet); FD_SET(sServerListen, &ReadSet);

for (int i=0; i<TotalSocket; i++) if (ClientSockets[i] != INVALID_SOCKET) FD_SET(ClientSockets[i], &ReadSet);

if ((ReadySock = select(0, &ReadSet, NULL, NULL, NULL)) == SOCKET_ERROR) { MessageBox(0, "Select filed", "Error", 0); }

//We have new connection (Есть новые подключения) if (FD_ISSET(sServerListen, &ReadSet)) { iSize = sizeof(clientaddr); ClientSockets[TotalSocket] = accept(sServerListen, (struct sockaddr *)&clientaddr,&iSize); if (ClientSockets[TotalSocket] == INVALID_SOCKET) { MessageBox(0, "Accept filed", "Error", 0); break; } TotalSocket++; } //We have data from client (Есть данные от клиента) for (int i=0; i<TotalSocket; i++) { if (ClientSockets[i] == INVALID_SOCKET) continue; if (FD_ISSET(ClientSockets[i], &ReadSet)) { char szRecvBuff[1024], szSendBuff[1024];




Содержание  Назад  Вперед