如何在 winsock 中使'send'无阻塞

How to make 'send' non-blocking in winsock

本文关键字:send 中使 winsock      更新时间:2023-10-16

我正在制作一个程序,它以固定的间隔向服务器发送UDP数据包,类似于以下内容:

while (!stop) {
    Sleep(fixedInterval);
    send(sock, pkt, payloadSize, flags);
 }

然而,由于send是阻塞调用(例如,当fixedInterval为20ms,并且对send的调用>20ms时),因此不能保证周期性。你知道我如何将send变成非阻塞操作吗?

您需要使用非阻塞套接字。发送/接收函数与阻塞或非阻塞操作的函数相同,但必须将套接字本身设置为非阻塞。

u_long mode = 1;  // 1 to enable non-blocking socket
ioctlsocket(sock, FIONBIO, &mode);

另外,请注意,使用非阻塞套接字是完全不同的。您需要确保成功处理WSAEWOULDBLOCK错误!:)

因此,使用非阻塞套接字可能会有所帮助,但仍然不能保证确切的周期。您最好从计时器驱动,而不是这个简单的循环,这样调用send的任何延迟,即使在非阻塞模式下,也不会影响计时。

API ioctlsocket可以做到这一点。您可以按如下方式使用它。但为什么不在winsock中使用I/O模型?

ioctlsocket(hsock,FIOBIO,(unsigned long *)&ul);

我的记忆很模糊,因为我使用UDP非阻塞可能已经15年了。

然而,有些事情你应该注意。

  1. 如果你要通过公共网络,只发送少量的数据包。如果客户端或服务器没有被编写来处理不完整的数据包,那么PATH MTU可能会让您绊倒。

  2. 请确保检查您是否已发送您认为必须发送的字节数。当你期望看到300个字节被发送,而接收端只得到248个时,这可能会变得很奇怪。客户端和服务器端都必须意识到这个问题。

  3. 请参阅此处,了解Linux用户的一些好建议。

  4. 请参阅此处了解UDP 的Unix套接字常见问题解答

  5. 这是一个很好的、通用的网络编程常见问题解答和示例页面。

测量发送所需的时间,然后将丢失的时间睡眠到20ms怎么样?