如果networking坏了,socket发生了什么事?

假设一个简单的networking模型:A已经成功创build了一个到B的TCP连接,并且它们正在像这样彼此通信

A <----------> B

我知道,如果A上的程序死亡(例如核心转储),那么将导致RST数据包到B.因此,任何B的读取尝试都将导致EOF,并且任何B的写入尝试都将导致SIGPIPE。 我对吗?

但是,如果假设networking在A上发生故障(如电缆/路由器故障),那么B的读写尝试会发生什么? 在我的情况下,所有的套接字已被设置为非阻塞。 因此,我不可能检测到networking错误?

顺便说一下,我注意到在socket中有一个选项SO_KEEPALIVE ,可能对我有用http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/ 。 但是我想知道如果将探测间隔设置为2〜3秒(默认为75秒),成本是多less? 看起来间隔configuration是全球性的,那么这会影响机器上的所有sockets吗?

最后的问题…说networking已经崩溃了,任何写入尝试都会导致EPIPE一段时间后。 但是,如果不是试图写入,我把这个套接字放入epoll设备,那么会发生什么呢? epoll_wait是否会返回EPOLLHUP或EPOLLERR事件?

Solutions Collecting From Web of "如果networking坏了,socket发生了什么事?"

还有很多其他的方法可以检测到TCP连接死亡

  • 有人掏出一条网线连接在一起。
  • 另一端的计算机被烧毁。
  • 中间一个NAT网关静静地断开连接
  • 另一端的操作系统崩溃了。
  • FIN数据包丢失。
  • 检测不到的错误:终端之间的路由器可能丢弃数据包(包括控制数据包) reff

在所有情况下,当您尝试在程序中通过SIGPIPE错误写入此原因并终止它时,可以知道它。

通过阅读()它不能知道其他方面是否存在。 Thants为什么SO_KEEPALIVE有用。 Keepalive是非侵入式的,在大多数情况下,如果您有疑问,您可以打开它,而不会有做错的风险。 但请记住,它会产生额外的网络流量,这可能会对路由器和防火墙产生影响。

这也会影响你的机器上的所有插座!(你是对的)。 而由于SO_KEEPALIVE增加流量并消耗CPU。 最好设置SIGPIPE句柄,如果有机会,应用程序会写入一个断开的连接。

在应用程序的合理位置也使用SO_KEEPALIVE。 在整个连接持续时间内使用它都很差(即当服务器在客户端查询时长时间工作时,请使用so_keepalive)。

在您的应用程序中设置探测间隔Dependends或者说应用层协议。

尽管启用TCP keepalive,你会最终检测到 – 至少在几个小时内。

说网络已经坏了,但是,而不是试图写,套接字被注入到一些epoll设备:

epoll中的第二个参数:

  n = epoll_wait (efd, events, MAXEVENTS, -1); 

设置与正确的事件相关的代码,好的做法是检查这个代码
谨慎如下。

 n = epoll_wait (efd, events, MAXEVENTS, -1); for (i = 0; i < n; i++) { if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { /* An error has occured on this fd, or the socket is not ready for reading (why were we notified then?) */ fprintf (stderr, "epoll error\n"); close (events[i].data.fd); continue; } else if (sfd == events[i].data.fd) { /* We have a notification on the listening socket, which means one or more incoming connections. */ // Do what you wants } } 

EPOLLRDHUP的意思是:
流套接字关闭连接,或关闭写入连接的一半。 (当使用Edge Triggered监视时,这个标志对编写简单的代码来检测对等关闭特别有用。

我知道,如果A上的程序死亡(例如核心转储),那么将导致RST数据包到B.因此,任何B的读取尝试都将导致EOF,并且任何B的写入尝试都将导致SIGPIPE。 我对吗?

部分。 RST在读取时会导致ECONNRESET,而不是EOF,在写入时会导致EPIPE。

但是,如果假设网络在A上发生故障(如电缆/路由器故障),那么B的读写尝试会发生什么? 在我的情况下,所有的套接字已被设置为非阻塞。 因此,我不可能检测到网络错误?

不可能单独读取,除非使用读取超时,例如通过select(),并将超时作为失败,这可能不是。 在写上你最终会得到一个EPIPE,但可能需要一些时间和几次尝试,由于缓冲和重试。