Функция recv (winsock.h)

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

Синтаксис

int recv(
  [in]  SOCKET s,
  [out] char   *buf,
  [in]  int    len,
  [in]  int    flags
);

Параметры

[in] s

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

[out] buf

Указатель на буфер для получения входящих данных.

[in] len

Длина (в байтах) буфера, на который указывает параметр buf .

[in] flags

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

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

Если ошибка не возникает, функция recv возвращает количество полученных байтов, а буфер, на который указывает параметр buf , будет содержать полученные данные. Если соединение было корректно закрыто, возвращаемое значение равно нулю.

В противном случае возвращается значение SOCKET_ERROR, а определенный код ошибки можно получить, вызвав WSAGetLastError.

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

Комментарии

Функция recv используется для чтения входящих данных в сокетах, ориентированных на подключение, или в сокетах без подключения. При использовании протокола, ориентированного на подключение, необходимо подключить сокеты перед вызовом recv. При использовании протокола без подключения сокеты должны быть привязаны перед вызовом recv.

Локальный адрес сокета должен быть известен. Для серверных приложений используйте явную функцию привязки или неявную функцию accept или WSAAccept . Явная привязка не рекомендуется использовать для клиентских приложений. Для клиентских приложений сокет может быть неявно привязан к локальному адресу с помощью connect, WSAConnect, sendto, WSASendTo или WSAJoinLeaf.

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

Для сокетов, ориентированных на подключение (например, тип SOCK_STREAM) вызов recv вернет столько данных, сколько доступно в настоящее время, вплоть до указанного размера буфера. Если сокет настроен для приема данных OOB в строке (параметр сокета SO_OOBINLINE), а данные OOB еще не прочитаны, будут возвращены только данные OOB. Приложение может использовать команду ioctlsocket или WSAIoctlSIOCATMARK , чтобы определить, нужно ли считывать дополнительные данные OOB.

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

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

Если в сокете нет доступных входящих данных, вызов recv блокируется и ожидает поступления данных в соответствии с правилами блокировки, определенными для WSARecv с флагом MSG_PARTIAL не установлен, если сокет не блокируется. В этом случае возвращается значение SOCKET_ERROR с кодом ошибки WSAEWOULDBLOCK. Функции select, WSAsyncSelect или WSAEventSelect можно использовать для определения времени поступления дополнительных данных.

Если сокет ориентирован на подключение и удаленная сторона корректно завершает подключение и все данные получены, то recv завершается немедленно с нулевыми полученными байтами. Если подключение было сброшено, восстановление завершится ошибкой WSAECONNRESET.

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

Значение Значение
MSG_PEEK Просматривает входящие данные. Данные копируются в буфер, но не удаляются из входной очереди.
MSG_OOB Обрабатывает данные вне диапазона (OOB).
MSG_WAITALL Запрос на получение завершится только при возникновении одного из следующих событий:
  • Буфер, предоставленный вызывающим объектом, полностью заполнен.
  • Соединение было закрыто.
  • Запрос был отменен или произошла ошибка.
Обратите внимание, что если базовый транспорт не поддерживает MSG_WAITALL или сокет находится в режиме без блокировки, этот вызов завершится ошибкой с WSAEOPNOTSUPP. Кроме того, если MSG_WAITALL указан вместе с MSG_OOB, MSG_PEEK или MSG_PARTIAL, этот вызов завершится ошибкой с WSAEOPNOTSUPP. Этот флаг не поддерживается для сокетов датаграмм и сокетов, ориентированных на сообщения.
 
Примечание При выполнении блокирующего вызова Winsock, например recv, Winsock может потребоваться дождаться сетевого события, прежде чем вызов сможет завершиться. В этой ситуации Winsock выполняет оповещенное ожидание, которое может быть прервано асинхронным вызовом процедуры (APC), запланированным в том же потоке. Выполнение другого блокирующего вызова Winsock внутри APC, который прервал текущий блокирующий вызов Winsock в том же потоке, приведет к неопределенному поведению, и клиенты Winsock никогда не должны пытаться его выполнять.
 

Пример кода

В следующем примере кода показано использование функции recv .
#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"

int __cdecl main() {

    //----------------------
    // Declare and initialize variables.
    WSADATA wsaData;
    int iResult;

    SOCKET ConnectSocket = INVALID_SOCKET;
    struct sockaddr_in clientService; 

    char *sendbuf = "this is a test";
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;
  
    //----------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != NO_ERROR) {
      printf("WSAStartup failed: %d\n", iResult);
      return 1;
    }

    //----------------------
    // Create a SOCKET for connecting to server
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ConnectSocket == INVALID_SOCKET) {
        printf("Error at socket(): %ld\n", WSAGetLastError() );
        WSACleanup();
        return 1;
    }

    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port of the server to be connected to.
    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
    clientService.sin_port = htons( 27015 );

    //----------------------
    // Connect to server.
    iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
    if ( iResult == SOCKET_ERROR) {
        closesocket (ConnectSocket);
        printf("Unable to connect to server: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    // Send an initial buffer
    iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive until the peer closes the connection
    do {

        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
            printf("Bytes received: %d\n", iResult);
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed: %d\n", WSAGetLastError());

    } while( iResult > 0 );

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}


Пример кода

Дополнительные сведения и еще один пример функции recv см. в разделе начало работы с Winsock.

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 winsock.h (включая Winsock2.h)
Библиотека Ws2_32.lib
DLL Ws2_32.dll

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

WSAsyncSelect

WSARecv

WSARecvEx

Функции Winsock

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

recvfrom

select

send

Сокета