Windows 上没有从 recvfrom 收到任何内容

Posted

技术标签:

【中文标题】Windows 上没有从 recvfrom 收到任何内容【英文标题】:Nothing received from recvfrom on windows 【发布时间】:2013-08-30 20:06:14 【问题描述】:

我在使用 recvfrom 的 Windows 8 上遇到了一些问题。我有一个绑定到 INADDR_ANY (0.0.0.0) 的套接字,我想在上面接收一些数据包。

问题是我在 Wireshark 中看到了这些数据包,但 recvfrom 从来没有告诉我接收到的大小大于 0。我尝试将套接字投标到 127.0.0.1 甚至我的本地 IPv4 地址,但我从来没有得到任何事物。使用的端口是 7321(本地)

我使用 ENet 库创建套接字,然后在 recvfrom 中使用该套接字。这是永远不会返回预期数据包的代码。

uint8_t* buffer; // max size needed normally (only used for stun)
buffer = (uint8_t*)(malloc(sizeof(uint8_t)*2048));
memset(buffer, 0, 2048);

socklen_t from_len;
struct sockaddr addr;

from_len = sizeof(addr);
int len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, &addr, &from_len); //m_host is of type ENetHost, the socket in it is a file descriptor like standard sockets

正如我所说,Wireshark 向我显示数据包时有点奇怪(如果你想知道,这是 STUN 响应)。

有人可以帮我找出可能导致此问题的缺失吗?

【问题讨论】:

我最近遇到了类似的问题,Wireshark 报告了数据包并且应用程序正在侦听,但它没有收到数据包。原来是路由表。也许这也是你的问题? (它在 Linux 上,所以我不知道如何在 Windows 上检查或修复它) 【参考方案1】:

您的addr 变量被声明为sockaddr。它需要声明为sockaddr_in(仅适用于 IPv4)或SOCKADDR_STORAGE(适用于 IPv4 和 IPv6),然后在将其传递给 recvfrom() 时将其类型转换为 sockaddr*

除此之外,您说recvfrom() 没有返回 >= 0。那么它实际上返回的是什么?如果它返回 0,则接收到一个长度为 0 的数据包(TCP 不可能,但 UDP 可能)。如果它返回 -1(又名SOCKET_ERROR),那么就会发生错误,因此请使用WSAGetLastError() 找出该错误实际上是什么。

【讨论】:

嗨,非常感谢您的帮助:首先:首先使用 sockarrd_in 没有帮助,可能是因为 recvfrom 函数等待 sockaddr* 作为第五个参数,而不是 sockaddr_in* 第二:总是返回 -1。我会尝试查看 WSAGHetLastError() 并告诉你结果是什么。 我遇到错误“无法立即完成非阻塞套接字操作” 首先,recvfrom() 不想要 sockaddr,它想要与底层套接字类型匹配的任何内容 - sockaddr_in 用于 IPv4,sockaddr_in6 用于 IPv6,等等。如果它真的想要 @987654334 @比第六个参数不存在,但它确实存在,因为第五个参数实际上是可变长度的。其次,WSAGetLastError() 给你一个错误代码,而不是一个字符串。您所说的错误消息表明您收到WSAEWOULDBLOCK (10035) 作为错误代码,如果您使用的是非阻塞套接字并且当时没有可读取的数据,这是完全正常的。 因此,如果 WireShark 看到数据到达您的 PC,但您的套接字没有接收到数据,那么操作系统没有将数据路由到您的套接字。这意味着您实际上并没有绑定到数据发送到的正确协议/IP/端口(使用 WireShark 不仅要仔细检查目标 IP/端口,还要仔细检查入站数据包的数据包类型和目标 MAC 地址),或者数据在到达您的应用程序之前被阻止,这本身可能表明存在防火墙/防病毒问题或操作系统路由表中的配置错误。 recvfrom 的参数好了,现在我正确地使用了 sockaddr_in。我确实有 10035 错误。我不明白的是套接字没有阻塞,但函数似乎永远看不到传入的数据(存在)。协议堆是以太网/IP/UDP,因此根据 ipconfig,传入数据包中的所有内容都很好(ip、ma​​c、正确的协议)。例如,我尝试使用阻塞套接字(未设置非阻塞选项)并且我在 0.0.0.0:7321 上也没有收到数据包(7321 再次成为事务使用的端口)【参考方案2】:

我可以想到您遇到问题的 2 个可能原因:

1) 您的 sendto 和 recvfrom 套接字上的端口可能不正确。所以说你正在向端口 6000 发送数据包,但你的 recvfrom 正在侦听端口 6001 或其他东西。只需仔细检查两个程序是否使用相同的端口。

2) Windows 防火墙。为了安全起见,我会以管理员身份运行该程序,但还要确保您允许您的程序通过 Windows 防火墙使用私有或公共网络进行通信。

【讨论】:

我尝试禁用所有防火墙(antivir+windows)并检查端口。套接字显然正在监听 0.0.0.0:7321,wireshark 告诉我数据包到达端口 7321,目标 IP 为 192.168.0.11(我的本地 IP 地址)。

以上是关于Windows 上没有从 recvfrom 收到任何内容的主要内容,如果未能解决你的问题,请参考以下文章

UDP 套接字上的 recvfrom() 返回 -1 但 WSAGetLastError() 返回 0

如何从 recvfrom() 检查消息大小?

套接字关闭时取消阻止 recvfrom

发送Icmp消息但什么都没有收到?

原始 UDP 套接字卡在 recvfrom 上

UDP中的recvfrom没有得到任何东西