【问题标题】:Can a socket be made non-blocking only for the recv() function?只能为 recv() 函数使套接字成为非阻塞的吗?
【发布时间】:2015-04-22 13:31:06
【问题描述】:

我希望能够在不必阻塞的情况下调用recv(),所以我想让它成为非阻塞的,但我不希望它在发送数据时是非阻塞的。那么是否可以只为recv() 函数将套接字设为非阻塞,或者阻塞/非阻塞模式会影响所有套接字函数?

【问题讨论】:

  • 您可以使用MSG_PEEK 标志来查看是否有要接收的内容。或使用例如select 超时为零。但是,对于 TCP 套接字,这些方法只能告诉您至少有 一个 字节要接收,您不知道实际可用的字节数。
  • 是的,但最后我检查了 recv() 如果有 1 个字节的数据就不会阻塞。
  • @Joachim Pileborg 但即使我使用了MSG_PEEKrecv() 仍然会阻塞。

标签: c++ c windows sockets


【解决方案1】:

对于windows,您可以使用ioctlsocket() 将套接字设置为非阻塞模式。不幸的是,这些设置适用于套接字上的所有操作。因此,对于您的情况,您必须在接收和发送之间切换。

供记录: 对于 linux,您可以在 recv() 调用参数中使用 MSG_DONTWAIT 标志。单个调用将是非阻塞的。

【讨论】:

  • 这不是可移植的,因为它不是标准标志。例如,它在 Windows winsock 库中不可用。
  • @JoachimPileborg 是的!我的错:我没有注意到 windows 标签。我已经编辑了我的答案。
  • 不能这样:unsigned long l; ioctlsocket(s, FIONREAD, &l);看看有没有数据要读取吗?
  • 您可以这样做以查看数据是否存在并切换回(注意:阅读MSDN链接上有关切换回阻塞的备注)。但是也许你也可以保持非阻塞模式,并且只有在 send() 会返回错误 WSAEWOULDBLOCK 时才切换回来?
  • 所以ioctlsocket(s, FIONREAD, &l); 也将套接字设置为非阻塞模式!看,我想要的不是查看有多少数据可用,而只是查看是否有数据可供读取。这不应该让我看到:recv(s, buffer, 1024, MSG_PEEK)?它对我不起作用,recv() 仍被阻止。
【解决方案2】:

没有办法只为recv() 函数使套接字非阻塞。

但是有一些接近(但有缺陷)的东西,那就是使用 ioctlsocket()FIONREAD 标志。例如:

unsigned long l;
ioctlsocket(s, FIONREAD, &l);

这个函数将返回(立即没有阻塞)有多少字节可供读取,虽然不是很准确(但我们并不关心这个,因为我们使用它来知道是否有数据要读取和不知道到底有多少字节)。

正如我之前提到的,这种方法是有缺陷的,因为它不会告诉你另一端何时断开连接,因为recv()在断开连接时返回0,如果没有数据,这个函数将返回0可用!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    • 2010-10-29
    • 2013-10-15
    • 1970-01-01
    • 2015-11-27
    • 2023-03-03
    • 1970-01-01
    相关资源
    最近更新 更多