在读取缓冲区已满时使用 select 检查可写套接字
Posted
技术标签:
【中文标题】在读取缓冲区已满时使用 select 检查可写套接字【英文标题】:Check socket writeable with select while read buffer full 【发布时间】:2016-09-16 04:16:40 【问题描述】:我正在尝试在使用send
之前检查套接字是否可写。这工作正常,除非套接字的读取缓冲区已满,然后 select
超时(至少这是我所期望的,行为是在不使用 recv
向套接字发送大量数据后,select
返回0.如果我读了一些东西再试一次,它会再次正常运行)。我希望完整的读取缓冲区不会阻止发送。我做错了什么?
int testwriteable(SOCKET socket)
timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 100; //100 us (microseconds)
fd_set set;
FD_ZERO(&set);
FD_SET(socket, &set);
//check for writable
return select(1, NULL, &set, NULL, &timeout);
【问题讨论】:
无法重现(Win 10 64 位,VS 2015 R3)。这整个函数给我的印象是perverse,你为单个套接字做了很多工作,返回的信息的值是可疑的。大概您正在检查返回 SOCKET_ERROR 的函数,并且您没有假设因为套接字是可写的,它将接受 所有 您要呈现给它的数据? 【参考方案1】:如果select()
使用此代码超时,则表示在整个超时期间发送缓冲区已满。
但是你做错了。您应该有一个主要的 select()
循环来驱动您的代码,而不是这种控制反转,并且您应该 (a) 在有东西要写的时候写,(b) 检测它何时返回 -1/EWOULDBLOCK/EAGAIN,并且(c) 此时将套接字 FD 添加到 writeFDs
集并推迟写入直到套接字变为可写。发生这种情况时,重试写入(这意味着您已将数据及其长度排队到某处),如果成功,则从 writeFDs
中删除套接字 FD。
【讨论】:
means the send buffer was full
,有点迂腐,表示send
、sendto
或WSASendto
会阻塞,也可能是因为非阻塞connect()
没有完成.
@kfsone 正确。然而,在这种情况下,他知道他的读取缓冲区已满,这意味着一个完整的连接。
我认为问题来自最终在读取缓冲区已满时阻止发送的另一方。由于另一端的发送部分是调试测试,它在读取线程上发送并阻塞,导致发送缓冲区最终确实填满,直到数据被读取。我不确定select
和其他事情是如何工作的,这会导致对问题的误解。感谢您指出正确的做事方式,我什至不知道ioctlsocket
(在 Windows 上)并且会读一点然后尝试重写部分代码。我一般不写c++/winapi代码。以上是关于在读取缓冲区已满时使用 select 检查可写套接字的主要内容,如果未能解决你的问题,请参考以下文章