4

使用 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。

4

2 回答 2

4

根据 MVP Alexander Nickolov的说法,Windows 中没有这样的设施。他还提到“良好的套接字代码”不使用类似 FIONWRITE 的 ioctl,但没有解释原因。

FIONBIO为了规避这个问题,您可以在您感兴趣的套接字上启用非阻塞 I/O(我猜是WSASend使用WSAGetLastError() == WSAEWOULDBLOCK已满(如文档中WSASend所述):

WSAEWOULBLOCK

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

另请阅读有关此错误代码的进一步说明

于 2012-12-26T15:43:05.477 回答
0

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

于 2012-12-29T02:12:11.170 回答