阻止TCP套接字:“send()”返回和错误处理

时间:2015-07-08 13:44:26

标签: c++ sockets tcp

根据这个答案Blocking sockets: when, exactly, does “send()” return?,阻塞套接字上的send()将在用户缓冲区被复制到内核缓冲区后立即返回。在传递失败的情况下(即,客户端没有收到字节),调用send()的进程如何被通知失败?

3 个答案:

答案 0 :(得分:1)

POSIX / BSD套接字API不提供TCP连接错误的中断驱动异步接口。由于TCP是可靠的,因此唯一的方式是数据未被传递,即连接本身是否存在阻止完全传递的故障。

您必须通过对(可能是非阻塞的)套接字执行某种同步操作来检测错误。最异步的机制是使用selectpoll(或OS特定的替代方案),它允许在单个同步调用中等待多个套接字上的状态更新。错误可能会出现在exceptfds select集中,或者在使用poll进行读取或写入时出现错误指示。此外,当您尝试读取或写入不再连接的套接字时,将传递错误。

答案 1 :(得分:1)

即使在正常操作下,数据包丢失和重新发送也是TCP / IP下的正常情况(拥塞控制依赖于数据包丢失!)。

这不是错误,因此您不应该收到错误(事实上,send无法返回错误,因为它已经在检测到错误时返回)。相反,数据报会一直重新发送,直到被确认(或直到TCP放弃)。

您通常将poll(或select)与阻塞套接字结合使用,以防万一另一端关闭连接或有人拔出以太网线,您将(嗯,应该,而不一定是立即查看POLLHUPPOLLRDHUPPOLLERR
当发生这种情况时,你知道没有人再在另一端听了。

请注意,路由器关闭和拔出电缆等事件不一定会破坏TCP连接,至少不会立即断开。只有在尝试发送时才能检测到此情况,并且无法访问目标。从理论上讲,这可能只在几分钟或几小时后发生(或者有人可能会将电缆重新插入电缆中,而你永远不会知道!)。

答案 2 :(得分:0)

简短回答无法知道数据是否已传送到远程端,除非将此类检查合并到会话层协议中。正是由于这个原因,像HTTP这样的协议要求远程端发送响应,即使对于PUT请求也是如此。

由于IP数据包遍历多个网络,并且可能很好地采用到目的地的不同路由,因此无法知道何时发送数据包是否将到达远程端。充其量主机将继续重新发送数据包,直到远程端确认数据包或超时后放弃。

因此,如果您想确定远程端是否收到数据,则需要远程端的响应作为协议的一部分。