本文内容
recvfrom 函数接收数据报并存储源地址。
语法
int recvfrom(
[in] SOCKET s,
[out] char *buf,
[in] int len,
[in] int flags,
[out] sockaddr *from,
[in, out, optional] int *fromlen
);
参数
[in] s
标识绑定套接字的描述符。
[out] buf
传入数据的缓冲区。
[in] len
buf 参数指向的缓冲区的长度(以字节为单位)。
[in] flags
一组选项,用于修改函数调用的行为,超出为关联套接字指定的选项。 有关更多详细信息,请参阅下面的“备注”。
[out] from
指向 sockaddr 结构中的缓冲区的可选指针,该缓冲区将在返回时保存源地址。
[in, out, optional] fromlen
指向 from 参数指向的缓冲区大小(以字节为单位)的可选指针。
返回值
如果未发生错误, recvfrom 将返回收到的字节数。 如果连接已正常关闭,则返回值为零。 否则,将返回值 SOCKET_ERROR,并且可以通过调用 WSAGetLastError 来检索特定的错误代码。
错误代码含义
WSANOTINITIALISED
在使用此函数之前,必须成功调用 WSAStartup 。
WSAENETDOWN
网络子系统失败。
WSAEFAULT
buf 或 from 参数指向的缓冲区不在用户地址空间中,或者 fromlen 参数太小,无法容纳对等地址的源地址。
WSAEINTR
(阻止) 调用已通过 WSACancelBlockingCall 取消。
WSAEINPROGRESS
阻止 Windows Sockets 1.1 调用正在进行,或者服务提供程序仍在处理回调函数。
WSAEINVAL
套接字未绑定 绑定,或者指定了未知标志,或者为启用了SO_OOBINLINE的套接字指定了MSG_OOB,或者仅) len 为零或负数的字节流样式套接字 (。
WSAEISCONN
套接字已连接。 无论连接套接字是面向连接的还是无连接的套接字,都不允许使用此函数。
WSAENETRESET
对于数据报套接字,此错误显示生存时间已经过期。
WSAENOTSOCK
s 参数中的描述符不是套接字。
WSAEOPNOTSUPP
MSG_OOB已指定,但套接字不是流样式(如类型SOCK_STREAM),与此套接字关联的通信域中不支持 OOB 数据,或者套接字是单向的,仅支持发送操作。
WSAESHUTDOWN
套接字已关闭;在调用关闭后,无法从套接字上重新显示SD_RECEIVE或SD_BOTH。
WSAEWOULDBLOCK
套接字标记为非阻塞, recvfrom 操作将阻止。
WSAEMSGSIZE
消息太大,无法容纳 到 buf 参数指向的缓冲区中,并且被截断。
WSAETIMEDOUT
由于网络故障或另一端的系统在未通知的情况下出现故障,连接已断开。
WSAECONNRESET
执行硬性或异常关闭的远程端重置了虚拟线路。 应用程序应关闭套接字;它不再可用。 在 UDP 数据报套接字上,此错误指示以前的发送操作导致 ICMP 端口无法访问 消息。
注解
recvfrom 函数读取已连接和未连接的套接字上的传入数据,并捕获从中发送数据的地址。 此函数通常用于无连接套接字。 套接字的本地地址必须是已知的。 对于服务器应用程序,这通常通过 绑定显式完成。 不建议对客户端应用程序进行显式绑定。 对于使用此函数的客户端应用程序,套接字可以通过 sendto、 WSASendTo 或 WSAJoinLeaf 隐式绑定到本地地址。
对于面向流的套接字(如类型为 SOCK_STREAM 的套接字),对 recvfrom 的调用将返回当前可用的信息量(最大为指定缓冲区的大小)。 如果套接字已配置为内联接收 OOB 数据 (套接字选项SO_OOBINLINE) 且 OOB 数据尚未读取,则仅返回 OOB 数据。 应用程序可以使用 ioctlsocket 或 WSAIoctlSIOCATMARK 命令来确定是否还有更多 OOB 数据需要读取。 对于面向连接的套接字,将忽略 from 和 fromlen 参数。
对于面向消息的套接字,从第一个排队的消息中提取数据,最大大小为指定的缓冲区大小。 如果数据报或消息大于指定的缓冲区,则用数据报的第一部分填充缓冲区, recvfrom 将生成错误 WSAEMSGSIZE。 例如,对于不可靠的协议 (,UDP) 会丢失多余的数据。 对于 UDP,如果收到的数据包不包含 (空) 的数据,则 来自 recvfrom 函数的返回值为零。
如果 from 参数不为零,并且套接字不面向连接, (类型SOCK_DGRAM例如) ,则发送数据的对等方的网络地址将复制到相应的 sockaddr 结构。 fromlen 指向的值初始化为此结构的大小,并在返回时进行修改,以指示存储在 sockaddr 结构中的地址的实际大小。
如果套接字上没有可用的传入数据, 则 recvfrom 函数会根据为 WSARecv 定义的阻止规则阻止并等待数据到达,除非套接字为非阻止,否则不会设置MSG_PARTIAL标志。 在这种情况下,返回值 SOCKET_ERROR,错误代码设置为 WSAEWOULDBLOCK。 select、WSAAsyncSelect 或 WSAEventSelect 可用于确定何时到达更多数据。
如果套接字面向连接,并且远程端已正常关闭连接,则对 recvfrom 的调用将立即完成,并且接收了零个字节。 如果连接已重置 ,则 recvfrom 将失败,并显示 错误 WSAECONNRESET。
flags 参数可用于影响为关联套接字指定的选项之外的函数调用行为。 此函数的语义由套接字选项和 flags 参数确定。 后者是使用以下任一值的按位 OR 运算符构造的。
值含义
MSG_PEEK
查看传入数据。 数据会复制到缓冲区中,但不会从输入队列中删除。
MSG_OOB
处理带外 (OOB) 数据。
注意 发出阻止 Winsock 调用(如 recvfrom)时,Winsock 可能需要等待网络事件,然后调用才能完成。 在这种情况下,Winsock 执行可发出警报的等待, (在同一线程上计划的 APC) 异步过程调用可能会中断该等待。 在 APC 内发出另一个阻止 Winsock 调用,该调用中断了同一线程上正在进行的阻止 Winsock 调用将导致未定义的行为,并且 Winsock 客户端绝不能尝试。
示例代码以下示例演示如何使用 recvfrom 函数。
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include
#include
#include
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int main()
{
int iResult = 0;
WSADATA wsaData;
SOCKET RecvSocket;
struct sockaddr_in RecvAddr;
unsigned short Port = 27015;
char RecvBuf[1024];
int BufLen = 1024;
struct sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
//-----------------------------------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error %d\n", iResult);
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (RecvSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
iResult = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
if (iResult != 0) {
wprintf(L"bind failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
wprintf(L"Receiving datagrams...\n");
iResult = recvfrom(RecvSocket,
RecvBuf, BufLen, 0, (SOCKADDR *) & SenderAddr, &SenderAddrSize);
if (iResult == SOCKET_ERROR) {
wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
}
//-----------------------------------------------
// Close the socket when finished receiving datagrams
wprintf(L"Finished receiving. Closing socket.\n");
iResult = closesocket(RecvSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
return 1;
}
//-----------------------------------------------
// Clean up and exit.
wprintf(L"Exiting.\n");
WSACleanup();
return 0;
}
Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。
Windows 8.1和Windows 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
WSAEventSelect
Winsock 函数
Winsock 参考
recv
send
sockaddr
socket