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
套接字未绑定 绑定,或者指定了未知标志,或者为启用了SO_OOBINLINE的套接字指定了MSG_OOB,或者仅对字节流套接字 () len 为零或负数。
WSAECONNABORTED
由于超时或其他故障,虚拟线路已终止。 因为套接字不可再用,应用程序应关闭套接字。
WSAETIMEDOUT
因为网络故障或对等系统无法响应,已经丢弃了连接。
WSAECONNRESET
执行硬性或异常关闭的远程端重置了虚拟线路。 因为套接字不可再用,应用程序应关闭套接字。 在 UDP 数据报套接字上,此错误将指示以前的发送操作导致 ICMP“端口无法访问”消息。

注解

recv 函数用于读取面向连接的套接字或无连接套接字上的传入数据。 使用面向连接的协议时,必须在调用 recv 之前连接套接字。 使用无连接协议时,必须在调用 recv 之前绑定套接字。

套接字的本地地址必须是已知的。 对于服务器应用程序,请使用显式 绑定 函数或隐式 acceptWSAAccept 函数。 不建议对客户端应用程序进行显式绑定。 对于客户端应用程序,套接字可以使用 connectWSAConnectsendtoWSASendToWSAJoinLeaf 隐式绑定到本地地址。

对于连接的或无连接的套接字, recv 函数限制接收消息的地址。 函数仅返回来自连接中指定的远程地址的消息。 来自其他地址的消息 (静默) 丢弃。

对于面向连接的套接字 (类型SOCK_STREAM例如) ,调用 recv 将返回当前可用的数据量,最大为指定的缓冲区大小。 如果已将套接字配置为对 OOB 数据进行内联接收, (套接字选项SO_OOBINLINE) 且 OOB 数据尚未读取,则仅返回 OOB 数据。 应用程序可以使用 ioctlsocketWSAIoctlSIOCATMARK 命令来确定是否还有更多 OOB 数据需要读取。

对于 (类型SOCK_DGRAM或其他面向消息的套接字) 的无连接套接字,数据从 连接 函数指定的目标地址提取第一个排队数据报 (消息) 。

如果数据报或消息大于指定的缓冲区,则会使用数据报的第一部分填充缓冲区,而 recv 将生成错误 WSAEMSGSIZE。 例如,对于不可靠的协议 (,UDP) 会丢失多余的数据;对于可靠的协议,数据由服务提供商保留,直到使用足够大的缓冲区调用 recv 成功读取。

如果套接字上没有可用的传入数据, 则 recv 调用会根据为 WSARecv 定义的阻止规则阻止并等待数据到达,除非套接字为非阻止,否则不会设置MSG_PARTIAL标志。 在这种情况下,返回值 SOCKET_ERROR,错误代码设置为 WSAEWOULDBLOCKselectWSAAsyncSelectWSAEventSelect 函数可用于确定何时到达更多数据。

如果套接字面向连接,并且远程端已正常关闭连接,并且已接收所有数据, 则 recv 将立即完成,且接收了零个字节。 如果连接已重置, 则 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) 异步过程调用可能会中断该等待。 在 APC 内发出另一个阻止 Winsock 调用,该调用中断了同一线程上正在进行的阻止 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 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。

Windows 8.1Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此功能。

要求

   
最低受支持的客户端 Windows 8.1,Windows Vista [桌面应用 |UWP 应用]
最低受支持的服务器 Windows Server 2003 [桌面应用 | UWP 应用]
目标平台 Windows
标头 winsock.h (包括 Winsock2.h)
Library Ws2_32.lib
DLL Ws2_32.dll

另请参阅

WSAAsyncSelect

WSARecv

WSARecvEx

Winsock 函数

Winsock 参考

recvfrom

select

send

socket