根据这个答案Blocking sockets: when, exactly, does “send()
” return?,阻塞套接字上的send()
将在用户缓冲区被复制到内核缓冲区后立即返回。在传递失败的情况下(即,客户端没有收到字节),调用send()
的进程如何被通知失败?
答案 0 :(得分:1)
POSIX / BSD套接字API不提供TCP连接错误的中断驱动异步接口。由于TCP是可靠的,因此唯一的方式是数据未被传递,即连接本身是否存在阻止完全传递的故障。
您必须通过对(可能是非阻塞的)套接字执行某种同步操作来检测错误。最异步的机制是使用select
或poll
(或OS特定的替代方案),它允许在单个同步调用中等待多个套接字上的状态更新。错误可能会出现在exceptfds
select
集中,或者在使用poll
进行读取或写入时出现错误指示。此外,当您尝试读取或写入不再连接的套接字时,将传递错误。
答案 1 :(得分:1)
即使在正常操作下,数据包丢失和重新发送也是TCP / IP下的正常情况(拥塞控制依赖于数据包丢失!)。
这不是错误,因此您不应该收到错误(事实上,send
无法返回错误,因为它已经在检测到错误时返回)。相反,数据报会一直重新发送,直到被确认(或直到TCP放弃)。
您通常将poll
(或select
)与阻塞套接字结合使用,以防万一另一端关闭连接或有人拔出以太网线,您将(嗯,应该,而不一定是立即查看POLLHUP
,POLLRDHUP
或POLLERR
。
当发生这种情况时,你知道没有人再在另一端听了。
请注意,路由器关闭和拔出电缆等事件不一定会破坏TCP连接,至少不会立即断开。只有在尝试发送时才能检测到此情况,并且无法访问目标。从理论上讲,这可能只在几分钟或几小时后发生(或者有人可能会将电缆重新插入电缆中,而你永远不会知道!)。
答案 2 :(得分:0)
简短回答无法知道数据是否已传送到远程端,除非将此类检查合并到会话层协议中。正是由于这个原因,像HTTP这样的协议要求远程端发送响应,即使对于PUT请求也是如此。
由于IP数据包遍历多个网络,并且可能很好地采用到目的地的不同路由,因此无法知道何时发送数据包是否将到达远程端。充其量主机将继续重新发送数据包,直到远程端确认数据包或超时后放弃。
因此,如果您想确定远程端是否收到数据,则需要远程端的响应作为协议的一部分。