Поделиться через


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

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

Синтаксис

int WSAAPI 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
Сокет не был привязан к bind, или был указан неизвестный флаг, или MSG_OOB был указан для сокета с включенной SO_OOBINLINE или (только для сокетов потока байтов) значение len равно нулю или отрицательному.
WSAECONNABORTED
Виртуальное подключение разорвано из-за тайм-аута или иного сбоя. Приложение должно закрыть сокет, поскольку он больше не может использоваться.
WSAETIMEDOUT
Соединение было разорвано из-за сбоя в сети или отсутствия ответа от одноранговой системы.
WSAECONNRESET
Виртуальное подключение было сброшено удаленной стороной путем прерывания. Приложение должно закрыть сокет, поскольку он больше не может использоваться. В сокете UDP-datagram эта ошибка указывает на то, что предыдущая операция отправки привела к сообщению 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 см. в разделе начало работы With 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 winsock2.h (включая Winsock2.h)
Библиотека Ws2_32.lib
DLL Ws2_32.dll

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

WSAsyncSelect

WSARecv

WSARecvEx

Функции Winsock

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

recvfrom

select

send

Сокета