【问题标题】:Determine how many bytes can be sent with winsock (FIONWRITE)?确定使用 winsock (FIONWRITE) 可以发送多少字节?
【发布时间】:2012-10-03 05:18:49
【问题描述】:

使用 select 我可以确定是否可以在不阻塞的情况下接收或发送任何字节。

通过这个函数,我可以确定可以接收多少字节:

function BytesAvailable(S: TSocket): Integer;
begin
  if ioctlsocket(S, FIONREAD, Result) = SOCKET_ERROR then
    Result := -1;
end;

还有没有办法确定可以发送多少字节?

所以我可以肯定,当我用 N 个字节调用 send 时,它会返回正好发送的 N 个字节(或 SOCKET_ERROR),但不会更少(发送缓冲区已满)。

FIONWRITE 不适用于 Winsock。

【问题讨论】:

  • 我读过几本指南说“严重的应用程序使用非阻塞 IO”,因为文档中关于阻塞行为的内容含糊不清,而且即使文档在那里,移植性也很差。

标签: select winsock send recv


【解决方案1】:

According to MVP Alexander Nickolov,Windows 中没有这样的功能。他还提到“好的套接字代码”不使用类似 FIONWRITE 的 ioctl,但没有解释原因。

为了规避这个问题,您可以在您感兴趣的套接字上启用非阻塞 I/O(我猜是使用 FIONBIO)。这样,当 WSASend 可以完成发送时,它将在此类套接字上成功没有阻塞,或者当缓冲区已满时以WSAGetLastError() == WSAEWOULDBLOCK 失败(如documentation for WSASend 中所述):

WSAEWOULDBLOCK

重叠的套接字:未完成的重叠 I/O 请求太多。 Nonoverlapped sockets:该socket被标记为非阻塞,发送操作不能立即完成。

另请阅读further notes about this error code

【讨论】:

    【解决方案2】:

    仅当套接字以阻塞模式运行并且套接字的出站缓冲区填满排队数据时,Winsock send() 才会阻塞。如果您在同一线程中管理多个套接字,请不要使用阻塞模式。如果一个接收器没有及时读取数据,可能会导致该线程上的所有连接都受到影响。改用非阻塞模式,然后当套接字进入阻塞状态时 send() 会报告,然后你可以使用 select() 来检测套接字何时可以再次接受新数据。更好的选择是改用重叠 I/O 或 I/O 完成端口。向操作系统提交出站数据,让操作系统处理所有等待您的事情,并在数据最终被接受/发送时通知您。在收到通知之前,不要为给定的套接字提交新数据。对于大量连接的可扩展性,I/O 完成端口通常是更好的选择。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多