Функция WSARecv (winsock2.h)

Функция WSARecv получает данные из подключенного сокета или ограниченного сокета без подключения.

Синтаксис

int WSAAPI WSARecv(
  [in]      SOCKET                             s,
  [in, out] LPWSABUF                           lpBuffers,
  [in]      DWORD                              dwBufferCount,
  [out]     LPDWORD                            lpNumberOfBytesRecvd,
  [in, out] LPDWORD                            lpFlags,
  [in]      LPWSAOVERLAPPED                    lpOverlapped,
  [in]      LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

Параметры

[in] s

Дескриптор, определяющий подключенный сокет.

[in, out] lpBuffers

Указатель на массив структур WSABUF . Каждая структура WSABUF содержит указатель на буфер и длину буфера (в байтах).

[in] dwBufferCount

Количество структур WSABUF в массиве lpBuffers .

[out] lpNumberOfBytesRecvd

Указатель на число (в байтах) данных, полученных этим вызовом, если операция получения завершается немедленно.

Используйте значение NULL для этого параметра, если параметр lpOverlapped не имеет значения NULL , чтобы избежать потенциально ошибочных результатов. Этот параметр может иметь значение NULL , только если параметр lpOverlapped не равен NULL.

[in, out] lpFlags

Указатель на флаги, используемые для изменения поведения вызова функции WSARecv . Дополнительные сведения см. в разделе «Примечания».

[in] lpOverlapped

Указатель на структуру WSAOVERLAPPED (игнорируется для непереключенных сокетов).

[in] lpCompletionRoutine

Тип: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

Указатель на подпрограмму завершения, вызываемую при завершении операции получения (игнорируется для неперекрывающихся сокетов).

Возвращаемое значение

Если ошибка не возникает и операция получения завершена немедленно, WSARecv возвращает ноль. В этом случае подпрограмма завершения будет уже запланирована для вызова, когда вызывающий поток перейдет в состояние предупреждения. В противном случае возвращается значение SOCKET_ERROR , а определенный код ошибки можно получить, вызвав WSAGetLastError. Код ошибки WSA_IO_PENDING указывает, что перекрывающаяся операция успешно запущена и что завершение будет указано позже. Любой другой код ошибки указывает на то, что перекрывающаяся операция не была успешно инициирована и не будет показаний завершения.

Код ошибки Значение
WSAECONNABORTED
Виртуальное подключение разорвано из-за тайм-аута или иного сбоя.
WSAECONNRESET
Для сокета потока виртуальная цепь была сброшена удаленной стороной. Приложение должно закрыть сокет, поскольку он больше не может использоваться. Для сокета датаграмм UDP эта ошибка указывает на то, что предыдущая операция отправки привела к сообщению ICMP "Порт недоступен".
WSAEDISCON
Сокеты ориентированы на сообщения, а виртуальная цепь была корректно закрыта удаленной стороной.
WSAEFAULT
Параметр lpBuffers не полностью содержится в допустимой части адресного пространства пользователя.
WSAEINPROGRESS
Выполняется блокирующий вызов Windows Sockets 1.1 или поставщик услуг по-прежнему обрабатывает функцию обратного вызова.
WSAEINTR
Вызов (блокирующий) был отменен функцией WSACancelBlockingCall .
WSAEINVAL
Сокет не был привязан (например, с помощью bind).
WSAEMSGSIZE
Сообщение было слишком большим, чтобы поместиться в указанный буфер, и (только для ненадежных протоколов) все конечные части сообщения, которые не помещались в буфер, были удалены.
WSAENETDOWN
Произошел сбой сетевой подсистемы.
WSAENETRESET
Для сокета, ориентированного на подключение, эта ошибка означает, что подключение было разорвано из-за активности действия, которое обнаружило сбой во время выполнения операции. Для сокета датаграмм эта ошибка указывает на то, что срок жизни истек.
WSAENOTCONN
Сокет не подключен.
WSAENOTSOCK
Дескриптор не является сокетом.
WSAEOPNOTSUPP
MSG_OOB указано, но сокет не является типом типа SOCK_STREAM, данные OOB не поддерживаются в домене связи, связанном с этим сокетом, или сокет является однонаправленным и поддерживает только операции отправки.
WSAESHUTDOWN
Сокет завершен; Невозможно вызвать WSARecv в сокете после вызова завершения работыс параметром SD_RECEIVE или SD_BOTH.
WSAETIMEDOUT
Соединение было разорвано из-за сбоя в сети или отсутствия ответа от одноранговой системы.
WSAEWOULDBLOCK

Windows NT: Перекрывающиеся сокеты: слишком много невыполненных перекрывающихся запросов ввода-вывода. Неперекрывающиеся сокеты. Сокет помечается как неблокируемый, и операция получения не может быть завершена немедленно.

WSANOTINITIALISED
Перед использованием этой функции должен быть выполнен успешный вызов WSAStartup .
WSA_IO_PENDING
Перекрываемая операция была успешно инициирована, а завершение будет указано позже.
WSA_OPERATION_ABORTED
Перекрываемая операция была отменена из-за закрытия сокета.

Комментарии

Функция WSARecv предоставляет некоторые дополнительные функции по сравнению со стандартной функцией recv в трех важных областях:

  • Его можно использовать в сочетании с перекрывающимися сокетами для выполнения перекрывающихся операций recv .
  • Он позволяет указать несколько буферов приема, что делает его применимым к типу точечной и сборочной операций ввода-вывода.
  • Параметр lpFlags используется как для входных данных, так и для выходных данных, что позволяет приложениям определить выходное состояние бита флага MSG_PARTIAL . Однако бит флага MSG_PARTIAL поддерживается не всеми протоколами.
Функция WSARecv используется для подключенных сокетов или ограниченных сокетов без подключения, указанных параметром s , и используется для чтения входящих данных. Локальный адрес сокета должен быть известен. Для серверных приложений это обычно выполняется явным образом с помощью привязки или неявно через accept или WSAAccept. Для клиентских приложений не рекомендуется использовать явную привязку. Для клиентских приложений сокет может быть неявно привязан к локальному адресу с помощью connect, WSAConnect, sendto, WSASendTo или WSAJoinLeaf.

Для подключенных сокетов без подключения эта функция ограничивает адреса, с которых принимаются полученные сообщения. Функция возвращает сообщения только с удаленного адреса, указанного в соединении. Сообщения с других адресов (автоматически) отклоняются.

Для перекрывающихся сокетов WSARecv используется для размещения одного или нескольких буферов, в которые будут помещены входящие данные по мере их доступности, после чего появляется указанное приложением указание завершения (вызов подпрограммы завершения или установка объекта события). Если операция не завершается немедленно, окончательное состояние завершения извлекается с помощью процедуры завершения или WSAGetOverlappedResult.

Примечание Все операции ввода-вывода, инициированные данным потоком, отменяются при выходе из этого потока. Для перекрывающихся сокетов ожидающие асинхронные операции могут завершиться сбоем, если поток закрывается до завершения операций. Дополнительные сведения см. в разделе ExitThread .
 
Если lpOverlapped и lpCompletionRoutine имеют значение NULL, сокет в этой функции будет рассматриваться как неперекрытый сокет.

Для непереключенных сокетов семантика блокировки идентична семантике стандартной функции recv , а параметры lpOverlapped и lpCompletionRoutine игнорируются. Все данные, уже полученные и буферизируемые транспортом, будут скопированы в указанные пользовательские буферы. В случае блокирующего сокета без данных, которые в настоящее время были получены и буферизованы транспортом, вызов будет блокироваться, пока не будут получены данные. Сокеты Windows 2 не определяют стандартный механизм блокировки времени ожидания для этой функции. Для протоколов, выступающих в качестве протоколов потока байтов, стек пытается вернуть как можно больше данных в соответствии с доступным пространством буфера и объемом полученных данных. Однако получения одного байта достаточно, чтобы разблокировать вызывающий объект. Нет никакой гарантии, что будет возвращено более одного байта. Для протоколов, действующих в качестве ориентированных на сообщения, для разблокировки вызывающего объекта требуется полное сообщение.

Примечание Параметры сокета SO_RCVTIMEO и SO_SNDTIMEO применяться только к блокирующим сокетам.
 
Указывает, действует ли протокол в качестве потока байтов, определяется параметром XP1_MESSAGE_ORIENTED и XP1_PSEUDO_STREAM в его WSAPROTOCOL_INFO структуре и параметром флага MSG_PARTIAL, передаваемого в эту функцию (для протоколов, которые ее поддерживают). В следующей таблице перечислены соответствующие сочетания ( звездочка (*) указывает, что в данном случае значение параметра этого бита не имеет значения).
XP1_MESSAGE_ORIENTED XP1_PSEUDO_STREAM MSG_PARTIAL Действует как
не задан * * Поток байтов
* Присвойте параметру * Поток байтов
set Не задано set Поток байтов
set Не задано не задан Ориентированные на сообщения
 

Буферы заполняются в том порядке, в котором они отображаются в массиве, на который указывает lpBuffers, и буферы упаковываются таким образом, чтобы не создавались отверстия.

Если эта функция выполняется в перекрывающемся режиме, поставщик службы Winsock отвечает за запись структур WSABUF перед возвращением из этого вызова. Это позволяет приложениям создавать массивы WSABUF на основе стека, на которые указывает параметр lpBuffers .

Для сокетов в стиле потока байтов (например, тип SOCK_STREAM) входящие данные помещаются в буферы до тех пор, пока буферы не будут заполнены, соединение не будет закрыто или не будет исчерпано внутренне буферизированных данных. Независимо от того, заполняют ли входящие данные все буферы, для перекрывающихся сокетов указывается завершение.

Для сокетов, ориентированных на сообщения (например, тип SOCK_DGRAM), входящее сообщение помещается в буферы вплоть до общего размера буферов, а для перекрывающихся сокетов отображается указание завершения. Если сообщение больше буферов, буферы заполняются первой частью сообщения. Если функция MSG_PARTIAL поддерживается базовым поставщиком услуг, флаг MSG_PARTIAL устанавливается в lpFlags , и последующие операции получения будут извлекать остальную часть сообщения. Если MSG_PARTIAL не поддерживается, но протокол является надежным, WSARecv создает ошибку WSAEMSGSIZE и последующую операцию получения с большим буфером можно использовать для получения всего сообщения. В противном случае (то есть протокол является ненадежным и не поддерживает MSG_PARTIAL) лишние данные теряются, и WSARecv создает ошибку WSAEMSGSIZE.

Для сокетов, ориентированных на подключение, WSARecv может указать корректное завершение виртуальной цепи одним из двух способов, которые зависят от того, является ли сокет потоком байтов или ориентирован на сообщение. Для потоков байтов ноль байтов, которые были прочитаны (как указано нулевым возвращаемым значением, указывающим на успешное выполнение, и значением lpNumberOfBytesRecvd , равным нулю), означает корректное закрытие и что больше байтов никогда не будет прочитано. Для сокетов, ориентированных на сообщения, где сообщение с нулевым байтом часто допускается, для указания корректного закрытия используется сбой с кодом ошибки WSAEDISCON . В любом случае код ошибки возврата WSAECONNRESET указывает на прерывание закрытия.

Параметр lpFlags можно использовать для влияния на поведение вызова функции за пределами параметров, указанных для связанного сокета. То есть семантика этой функции определяется параметрами сокета и параметром lpFlags . Последнее создается с помощью побитового оператора OR с любым из значений, перечисленных в следующей таблице.

Значение Значение
MSG_PEEK Просматривает входящие данные. Данные копируются в буфер, но не удаляются из входной очереди.

Этот флаг действителен только для неперекрывающихся сокетов.

MSG_OOB Обрабатывает данные OOB.
MSG_PARTIAL Этот флаг предназначен только для сокетов, ориентированных на сообщения. На выходе этот флаг указывает, что указанные данные являются частью сообщения, передаваемого отправителем. Остальные части сообщения будут указаны в последующих операциях получения. Последующая операция получения с снятным флагом MSG_PARTIAL указывает на конец сообщения отправителя.

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

MSG_PUSH_IMMEDIATE Этот флаг предназначен только для сокетов, ориентированных на поток. Этот флаг позволяет приложению, использующим потоковые сокеты, сообщать поставщику транспорта не задерживать завершение частично заполненных ожидающих запросов на получение. Это указание поставщику транспорта на то, что приложение готово как можно скорее получить любые входящие данные, не обязательно дожидаясь оставшейся части данных, которые могут по-прежнему находиться в пути. То, что представляет собой частично заполненный ожидающий запрос на получение, является вопросом, зависящим от транспорта.

В случае TCP это относится к ситуации, когда входящие сегменты TCP помещаются в буфер данных запроса на получение, где ни один из сегментов TCP не указал битовое значение push-передачи, равное 1. В этом случае TCP может хранить частично заполненный запрос на получение немного дольше, чтобы позволить остальным данным поступать с сегментом TCP, для которого бит push-уведомлений имеет значение 1. Этот флаг указывает TCP не удерживать запрос на получение, а немедленно завершить его.

Использовать этот флаг для передачи больших блоков не рекомендуется, так как обработка частичных блоков часто не является оптимальной. Этот флаг полезен только в тех случаях, когда получение и обработка частичных данных немедленно помогает уменьшить задержку обработки.

Этот флаг является указанием, а не фактической гарантией.

Этот флаг поддерживается в Windows 8.1, Windows Server 2012 R2 и более поздних версий.

MSG_WAITALL Запрос на получение завершится только при возникновении одного из следующих событий:
  • Буфер, предоставленный вызывающим объектом, полностью заполнен.
  • Соединение было закрыто.
  • Запрос был отменен или произошла ошибка.

Имейте в виду, что если базовый поставщик транспорта не поддерживает MSG_WAITALL или сокет находится в режиме без блокировки, этот вызов завершится ошибкой с WSAEOPNOTSUPP. Кроме того, если MSG_WAITALL указан вместе с MSG_OOB, MSG_PEEK или MSG_PARTIAL, этот вызов завершится ошибкой wSAEOPNOTSUPP.

Этот флаг не поддерживается для сокетов датаграмм и сокетов, ориентированных на сообщения.

 

Для сокетов, ориентированных на сообщения, бит MSG_PARTIAL задается в параметре lpFlags , если получено частичное сообщение. Если получено полное сообщение, MSG_PARTIAL очищается в lpFlags. В случае отложенного завершения значение, на которое указывает lpFlags , не обновляется. После указания завершения приложение должно вызвать WSAGetOverlappedResult и проверить флаги, указанные параметром lpdwFlags .

Примечание При выполнении блокирующего вызова Winsock, например WSARecv , с параметром lpOverlapped , имеющим значение NULL, Winsock может потребоваться дождаться сетевого события перед завершением вызова. В этой ситуации Winsock выполняет оповещенное ожидание, которое может быть прервано асинхронным вызовом процедуры (APC), запланированным в том же потоке. Выполнение другого блокирующего вызова Winsock внутри APC, который прервал текущий блокирующий вызов Winsock в том же потоке, приведет к неопределенному поведению, и клиенты Winsock никогда не должны пытаться его выполнять.
 

Перекрывающиеся сокеты ввода-вывода

Если перекрывающаяся операция завершается немедленно, WSARecv возвращает нулевое значение, а параметр lpNumberOfBytesRecvd обновляется на количество полученных байтов, а биты флагов, указанные параметром lpFlags , также обновляются. Если перекрывающаяся операция успешно запущена и завершится позже, WSARecv возвращает SOCKET_ERROR и указывает код ошибки WSA_IO_PENDING. В этом случае lpNumberOfBytesRecvd и lpFlags не обновляются. После завершения перекрывающейся операции объем передаваемых данных указывается либо с помощью параметра cbTransferred в подпрограмме завершения (если указано), либо с помощью параметра lpcbTransfer в WSAGetOverlappedResult. Значения флагов получаются путем проверки параметра lpdwFlagsWSAGetOverlappedResult.

Функция WSARecv с использованием перекрывающихся операций ввода-вывода может вызываться из подпрограммы завершения предыдущей функции WSARecv, WSARecvFrom, WSASend или WSASendTo . Для заданного сокета подпрограммы завершения ввода-вывода не будут вложенными. Это позволяет полностью выполнять передачу конфиденциальных во времени данных в контексте вытеснения.

Параметр lpOverlapped должен быть действителен в течение всего периода перекрываемой операции. Если одновременно выполняется несколько операций ввода-вывода, каждая из них должна ссылаться на отдельную структуру WSAOVERLAPPED .

Если параметр lpCompletionRoutine имеет значение NULL, параметр hEventобъекта lpOverlapped получает сигнал о завершении перекрываемой операции, если он содержит допустимый дескриптор объекта события. Приложение может использовать WSAWaitForMultipleEvents или WSAGetOverlappedResult для ожидания или опроса объекта события.

Если значение lpCompletionRoutine не равно NULL, параметр hEvent игнорируется и может использоваться приложением для передачи контекстных сведений в подпрограмму завершения. Вызывающий объект, который передает lpCompletionRoutine, отличный от NULL, а затем вызывает WSAGetOverlappedResult для того же перекрывающегося запроса ввода-вывода, может не задать для параметра fWait для этого вызова WSAGetOverlappedResult значение TRUE. В этом случае использование параметра hEvent не определено, и попытка ожидания параметра hEvent приведет к непредсказуемым результатам.

Процедура завершения соответствует тем же правилам, которые предусмотрены для процедур завершения файлового ввода-вывода Windows. Подпрограмма завершения не будет вызываться до тех пор, пока поток не будет находиться в состоянии ожидания, доступном для предупреждений, например при вызове функции WSAWaitForMultipleEvents с параметром fAlertable, равнымTRUE .

Ниже приведен прототип процедуры завершения.


void CALLBACK CompletionROUTINE(
  IN DWORD dwError, 
  IN DWORD cbTransferred, 
  IN LPWSAOVERLAPPED lpOverlapped, 
  IN DWORD dwFlags
);

CompletionRoutine — это заполнитель для имени определяемой приложением или библиотекой функции. DwError указывает состояние завершения для перекрываемой операции, как указано в lpOverlapped. Параметр cbTransferred указывает количество полученных байтов. Параметр dwFlags содержит сведения, которые появились бы в lpFlags , если бы операция получения была завершена немедленно. Эта функция не возвращает значение.

Возвращаясь из этой функции, можно использовать для этого сокета вызов другой подпрограммы отложенного завершения. При использовании WSAWaitForMultipleEvents все подпрограммы завершения ожидания вызываются до того, как ожидание потока с оповещением будет удовлетворено кодом возврата WSA_IO_COMPLETION. Подпрограммы завершения можно вызывать в любом порядке, не обязательно в том же порядке, в каком выполняются перекрывающиеся операции. Однако размещенные буферы гарантированно заполняются в том же порядке, в котором они указаны.

Если вы используете порты завершения ввода-вывода, имейте в виду, что порядок вызовов WSARecv также является порядком заполнения буферов. WSARecv не следует вызывать в одном сокете одновременно из разных потоков, так как это может привести к непредсказуемому буферному порядку.

Пример кода

В следующем примере показано, как использовать функцию WSARecv в режиме перекрывающихся операций ввода-вывода.
#ifndef UNICODE
#define UNICODE
#endif

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <Windows.h>

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>

// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")

#pragma warning(disable: 4127)  // Conditional expression is a constant

#define DATA_BUFSIZE 4096

int __cdecl main(int argc, char **argv)
{
    WSADATA wsd;
    struct addrinfo *result = NULL, *ptr = NULL, hints;
    WSAOVERLAPPED RecvOverlapped;
    SOCKET ConnSocket = INVALID_SOCKET;
    WSABUF DataBuf;
    DWORD RecvBytes, Flags;
    char buffer[DATA_BUFSIZE];

    int err = 0;
    int rc;

    if (argc != 2) {
        wprintf(L"usage: %s server-name\n", argv[0]);
        return 1;
    }
    // Load Winsock
    rc = WSAStartup(MAKEWORD(2, 2), &wsd);
    if (rc != 0) {
        wprintf(L"Unable to load Winsock: %d\n", rc);
        return 1;
    }
    // Make sure the hints struct is zeroed out
    SecureZeroMemory((PVOID) & hints, sizeof (struct addrinfo));

    // Initialize the hints to retrieve the server address for IPv4
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    rc = getaddrinfo(argv[1], "27015", &hints, &result);
    if (rc != 0) {
        wprintf(L"getaddrinfo failed with error: %d\n", rc);
        return 1;
    }

    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

        ConnSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (ConnSocket == INVALID_SOCKET) {
            wprintf(L"socket failed with error: %d\n", WSAGetLastError());
            freeaddrinfo(result);
            return 1;
        }

        rc = connect(ConnSocket, ptr->ai_addr, (int) ptr->ai_addrlen);
        if (rc == SOCKET_ERROR) {

            if (WSAECONNREFUSED == (err = WSAGetLastError())) {
                closesocket(ConnSocket);
                ConnSocket = INVALID_SOCKET;
                continue;
            }
            wprintf(L"connect failed with error: %d\n", err);
            freeaddrinfo(result);
            closesocket(ConnSocket);
            return 1;
        }
        break;
    }
    if (ConnSocket == INVALID_SOCKET) {
        wprintf(L"Unable to establish connection with the server!\n");
        freeaddrinfo(result);
        return 1;
    }

    wprintf(L"Client connected...\n");

    // Make sure the RecvOverlapped struct is zeroed out
    SecureZeroMemory((PVOID) & RecvOverlapped, sizeof (WSAOVERLAPPED));

    // Create an event handle and setup an overlapped structure.
    RecvOverlapped.hEvent = WSACreateEvent();
    if (RecvOverlapped.hEvent == NULL) {
        wprintf(L"WSACreateEvent failed: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ConnSocket);
        return 1;
    }

    DataBuf.len = DATA_BUFSIZE;
    DataBuf.buf = buffer;

    // Call WSARecv until the peer closes the connection
    // or until an error occurs
    while (1) {

        Flags = 0;
        rc = WSARecv(ConnSocket, &DataBuf, 1, &RecvBytes, &Flags, &RecvOverlapped, NULL);
        if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError()))) {
            wprintf(L"WSARecv failed with error: %d\n", err);
            break;
        }

        rc = WSAWaitForMultipleEvents(1, &RecvOverlapped.hEvent, TRUE, INFINITE, TRUE);
        if (rc == WSA_WAIT_FAILED) {
            wprintf(L"WSAWaitForMultipleEvents failed with error: %d\n", WSAGetLastError());
            break;
        }

        rc = WSAGetOverlappedResult(ConnSocket, &RecvOverlapped, &RecvBytes, FALSE, &Flags);
        if (rc == FALSE) {
            wprintf(L"WSARecv operation failed with error: %d\n", WSAGetLastError());
            break;
        }

        wprintf(L"Read %d bytes\n", RecvBytes);

        WSAResetEvent(RecvOverlapped.hEvent);

        // If 0 bytes are received, the connection was closed
        if (RecvBytes == 0)
            break;
    }

    WSACloseEvent(RecvOverlapped.hEvent);
    closesocket(ConnSocket);
    freeaddrinfo(result);

    WSACleanup();

    return 0;
}


Windows Phone 8. Эта функция поддерживается для приложений Магазина Windows Phone Windows Phone 8 и более поздних версий.

Windows 8.1 и Windows Server 2012 R2: эта функция поддерживается для приложений Магазина Windows на Windows 8.1, Windows Server 2012 R2 и более поздних версий.

Требования

   
Минимальная версия клиента Windows 8.1, Windows Vista [классические приложения | Приложения UWP]
Минимальная версия сервера Windows Server 2003 [классические приложения | Приложения UWP]
Целевая платформа Windows
Header winsock2.h
Библиотека Ws2_32.lib
DLL Ws2_32.dll

См. также раздел

WSABUF

WSACloseEvent

WSACreateEvent

WSAGetOverlappedResult

WSAOVERLAPPED

WSASocket

WSAWaitForMultipleEvents

Функции Winsock

Справочник по Winsock

Recv