TCP中出现的错误及处理
首先要明确,TCP连接关闭有两种方法其一是正常的四次挥手,会经历多个状态,最后连接正常关闭,还有一种方法是连接异常关闭,即此时对方希望连接能够尽快关闭,发送RST包后连接会直接关闭,不会再出现上述的状态转换
进程正常关闭/进程被杀死/服务器重启
- 这三种情况下,服务器关闭套接字,并发起第一次挥手操作,客户端收到FIN包,并返回ack,
- 此时连接处于半关闭状态,客户端并不知道服务器已经关闭,客户端如果继续向服务器write数据,那么服务器会向客户端发送RST包,
- 当客户端收到RST包时,如果再write,那么将返回EPIPE错误,同时会导致SIGPIPE信号,如果从收到RST包的连接上read,那么将返回ECONNRESET错误
- 如果客户端是使用的select/epoll等,那么当select/epoll收到RST会返回连接可读,即调用read返回ECONNRESET错误(但是根据muduo库测试最后epoll收到RST后返回可读,但是read会返回0,此处存疑),注意这里所说的错误是errno的值,同时也是套接字的待处理错误,所以此时调用getsockopt所获得的error是相应的错误,epoll/select所监视的某个socket上如果出现了错误,那么将会返回可读可写
服务器崩溃/服务器不可达
-
服务器崩溃时,如果有数据发送,那么TCP会重传数据(无论是客户端自己发送的数据还是保活探测),在重传一定次数后(一般是12次),客户端会给对端发送RST以关闭该连接,此时会将套接字的待处理错误设置为ETIMEDOUT,当此时再read/write时就会返回该错误。
-
服务器不可达时,如果有数据发送,那么TCP会重传数据(无论是客户端自己发送的数据还是保活探测),在重传一定次数后(一般是12次),客户端会给对端发送RST以关闭该连接,此时会将套接字的待处理错误设置为EHOSTUNREACH,当此时再read/write时就会返回该错误。
服务器崩溃重启
- 服务器崩溃重启,此时连接已经不复存在,此时如果客户端给服务器发送数据,那么会收到RST包,处理方法和第一种情况一样
epoll的EPOLLERR何时触发
- 对于epoll而言如果收到了RST包,那么epoll所触发的操作是 EPOLLIN+EPOLLRDHUP+EPOLLHUP+EPOLLERR
- 对端关闭连接收到FIN包会触发EPOLLRDHUP+EPOLLIN
- 本端shutdown读写时,如果不把该socket从epoll中移除,那么LT下会不断触发EPOLLIN+EPOLLHUP+EPOLLRDHUP
- 本端shtdown读,LT下会不断触发EPOLLIN+EPOLLRDHUP
注意,当close套接字时,该套接字会被内核自动从epoll中移除,但是shutdown的套接字则不会,如果不手动把shutdown的套接字移除,那么会不断触发EPOLLIN+EPOLLHUP+EPOLLRDHUP
https://blog.csdn.net/halfclear/article/details/78061771?utm_source=blogxgwz8
来源:CSDN
作者:张火油
链接:https://blog.csdn.net/hdadiao/article/details/104614610