Connection reset原因分析和解决方案

发布时间:

在使用 HttpClient 调用后台 resetful 服务时,“Connection reset” 是一个比较常见的问题,有同学跟我私信说被这个问题困扰很久了,今天就来分析下,希望能帮到大家。
 
从日志中可以看到是 Socket 套接字在 read 数据时抛出了该错误。
 
原因分析
导致 “Connection reset” 的原因是服务器端因为某种原因关闭了 Connection,而客户端依然在读写数据,此时服务器会返回复位标志 “RST”,然后此时客户端就会提示 “java.net.SocketException: Connection reset”。
 
TCP回顾
可能有同学对复位标志 “RST” 还不太了解,这里简单解释一下:
 
TCP 建立连接时需要三次握手,在释放连接需要四次挥手;例如三次握手的过程如下:
 
第一次握手:客户端发送 syn 包(syn=j)到服务器,并进入 SYN_SENT 状态,等待服务器确认;
第二次握手:服务器收到 syn 包,并会确认客户的 SYN(ack=j+1),同时自己也发送一个 SYN 包(syn=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;
第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK (ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED(TCP 连接成功)状态,完成三次握手。
可以看到握手时会在客户端和服务器之间传递一些 TCP 头信息,比如 ACK 标志、SYN 标志以及挥手时的 FIN 标志等。
 
除了以上这些常见的标志头信息,还有另外一些标志头信息,比如推标志 PSH、复位标志 RST 等。其中复位标志 RST 的作用就是 “复位相应的 TCP 连接”。
 
TCP 连接和释放时还有许多细节,比如半连接状态、半关闭状态等。详情请参考这方面的巨著《TCP/IP 详解》和《UNIX 网络编程》。
阅读全文