Dav*_*uss 15 c sockets linux nonblocking
非阻塞套接字的手册页中详细记录了两个案例:
没有记录的非阻塞套接字是:
是否可以安全地假设send()甚至会在一个字节的数据上返回EAGAIN/EWOULDBLOCK?或者,非阻塞程序是否应该再次发送()以获得结论性的EAGAIN/EWOULDBLOCK?我担心在插座上放一个EPOLLOUT观察器,如果它实际上没有处于"阻塞"状态以响应它的出现.
显然,后一种策略(再次尝试获得某种结论)具有明确定义的行为,但它更加冗长并且会对性能产生影响.
Dam*_*mon 28
呼叫send
有三种可能的结果:
send
成功并返回接受的字节数(可能少于您要求的字节数).send
.send
阻止send
使用EWOULDBLOCK
/EAGAIN
send
失败并出现其他错误如果接受的字节数send
小于您要求的数量,则这意味着发送缓冲区现在已完全填满.然而,这对于未来的任何电话来说都是纯粹的间接和非授权send
.
返回的信息send
仅仅是您呼叫时当前状态的"快照" send
.当send
您返回时或send
再次拨打电话时,此信息可能已经过时.当程序在内部时send
,或者在一个纳秒之后,或者在任何其他时间,网卡可能会在数据报上放置数据报- 无法知道.您将知道下一个呼叫何时成功(或何时不成功).
换句话说,但这并不意味着下一次调用send
将返回EWOULDBLOCK
/ EAGAIN
(或者套接字未无阻塞会阻止).尝试直到所谓的"得出结论EWOULDBLOCK
"是正确的做法.
如果 send() 返回与传输缓冲区相同的长度,则整个传输成功完成,套接字可能处于阻塞状态,也可能不处于阻塞状态。
不。套接字保持在它所处的模式:在这种情况下,非阻塞模式,在下面始终假设。
如果 send() 返回 -1 并且 errno 是 EAGAIN/EWOULDBLOCK,则没有任何传输完成,程序需要等待套接字不再阻塞。
直到发送缓冲区不再满为止。套接字保持非阻塞模式。
如果 send() 返回一个小于缓冲区大小的正值。
套接字发送缓冲区中只有那么多空间。
假设 send() 会阻塞甚至多一个字节的数据是否安全?
“假设 [它] 会阻塞”根本不“安全”。不会。它处于非阻塞模式。EWOULDBLOCK 意味着它会在阻塞模式下被阻塞。
还是非阻塞程序应该再尝试一次 send() 以获得结论性的 EAGAIN/EWOULDBLOCK?
随你(由你决定。无论您决定如何,API 都可以工作。
我担心在套接字上放置一个 EPOLLOUT 观察器,如果它实际上没有阻塞的话。
这不是“阻止”。它没有阻止任何事情。它处于非阻塞模式。发送缓冲区在那一刻被填满。过一会可能就完全空了。
我看不出你在担心什么。如果您有待处理的数据并且上次写入没有全部发送,请选择可写性,并在获得时写入。如果这样的写入发送了所有内容,则下次不要选择可写性。
套接字通常是可写的,除非它们的发送缓冲区已满,所以不要一直选择可写性,因为您只会得到一个自旋循环。