几种TCP连接中出现RST的情况
2015-08-10 15:10
1001 查看
UNIX网络编程上说:产生RST的三个条件是:目的地为某端口的SYN到达,然而在该端口上并没有正在监听
的服务器;TCP想取消一个已有链接;TCP接收到一个根本不存在的连接上的分节。
几种TCP连接中出现RST的情况
1 端口未打开2 请求超时
3 提前关闭
4 在一个已关闭的socket上收到数据
总结
参考文献:
应该没有人会质疑,现在是一个网络时代了。应该不少程序员在编程中需要考虑多机、局域网、广域网的各种问题。所以网络知识也是避免不了学习的。而且笔者一直觉得TCP/IP网络知识在一个程序员知识体系中必需占有一席之地的。
在TCP协议中RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。
其实在网络编程过程中,各种RST错误其实是比较难排查和找到原因的。下面我列出几种会出现RST的情况。
1 端口未打开
服务器程序端口未打开而客户端来连接。这种情况是最为常见和好理解的一种了。去telnet一个未打开的TCP的端口可能会出现这种错误。这个和操作系统的实现有关。在某些情况下,操作系统也会完全不理会这些发到未打开端口请求。比如在下面这种情况下,主机241向主机114发送一个SYN请求,表示想要连接主机114的40000端口,但是主机114上根本没有打开40000这个端口,于是就向主机241发送了一个RST。这种情况很常见。特别是服务器程序core dump之后重启之前连续出现RST的情况会经常发生。
![](http://static.oschina.net/uploads/space/2013/0504/102501_iHAp_247956.jpg)
当然在某些操作系统的主机上,未必是这样的表现。比如向一台WINDOWS7的主机发送一个连接不存在的端口的请求,这台主机就不会回应。
2 请求超时
曾经遇到过这样一个情况:一个客户端连接服务器,connect返回-1并且error=EINPROGRESS。 直接telnet发现网络连接没有问题。ping没有出现丢包。用抓包工具查看,客户端是在收到服务器发出的SYN之后就莫名其妙的发送了RST。比如像下面这样:
![](http://static.oschina.net/uploads/space/2013/0504/103527_RRmR_247956.jpg)
有89、27两台主机。主机89向主机27发送了一个SYN,表示希望连接8888端口,主机27回应了主机89一个SYN表示可以连接。但是主机27却很不友好,莫名其妙的发送了一个RST表示我不想连接你了。
后来经过排查发现,在主机89上的程序在建立了socket之后,用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间为100ms。而我们看上面的抓包结果表示,从主机89发出SYN到接收SYN的时间多达110ms。(从15:01:27.799961到15:01:27.961886, 小数点之后的单位是微秒)。因此主机89上的程序认为接收超时,所以发送了RST拒绝进一步发送数据。
3 提前关闭
关于TCP,我想我们在教科书里都读到过一句话,'TCP是一种可靠的连接'。 而这可靠有这样一种含义,那就是操作系统接收到的来自TCP连接中的每一个字节,我都会让应用程序接收到。如果应用程序不接收怎么办?你猜对了,RST。看两段程序:
?
?
然后再看一下client的代码:
?
![](http://static.oschina.net/uploads/space/2013/0504/112511_6jx3_247956.jpg)
前三行就是TCP的3次握手,从第四行开始看,客户端的49660端口向服务器的9877端口发送了5000个字节的数据,然后服务器端发送了一个ACK进行了确认,紧接着服务器向客户端发送了一个RST断开了连接。和我们的预期一致。
4 在一个已关闭的socket上收到数据
如果某个socket已经关闭,但依然收到数据也会产生RST。代码如下:
客户端:
?
?
![](http://static.oschina.net/uploads/space/2013/0505/154737_5Uz3_247956.jpg)
总结
总结,本文讲了几种TCP连接中出现RST的情况。实际上肯定还有无数种的RST发生,我以后会慢慢收集把更多的例子加入这篇文章。参考文献:
1 从TCP协议的原理来谈谈RST攻击 http://russelltao.iteye.com/blog/14053492 TCP客户-服务器程序例子http://blog.csdn.net/youkuxiaobin/article/details/6917880
tcp 出现rst情况整理
正常情况tcp四层握手关闭连接,rst基本都是异常情况,整理如下:1. GFW
2. 对方端口未打开,发生在连接建立
如果对方sync_backlog满了的话,sync简单被丢弃,表现为超时,而不会rst
3. close Socket 时recv buffer 不为空
例如,客户端发了两个请求,服务器只从buffer 读取第一个请求处理完就关闭连接,tcp层认为数据没有正确提交到应用,使用rst关闭连接。
3. 移动链路
移动网络下,国内是有5分钟后就回收信令,也就是IM产品,如果心跳>5分钟后服务器再给客户端发消息,就会收到rst。也要查移动网络下IM 保持<5min 心跳。
4. 负载等设备
负载设备需要维护连接转发策略,长时间无流量,连接也会被清除,而且很多都不告诉两层机器,新的包过来时才通告rst。
Apple push 服务也有这个问题,而且是不可预期的偶发性连接被rst;rst 前第一个消息write 是成功的,而第二条写才会告诉你连接被重置,
曾经被它折腾没辙,因此打开每2秒一次tcp keepalive,固定5分钟tcp连接回收,而且发现连接出错时,重发之前10s内消息。
5. SO_LINGER 应用强制使用rst 关闭
该选项会直接丢弃未发送完毕的send buffer,可能造成业务错误,慎用; 当然内网服务间http
client 在收到应该时主动关闭,使用改选项,会节省资源。
好像曾经测试过haproxy 某种配置下,会使用rst关闭连接,少了网络交互而且没有TIME_WAIT
问题
6. 超过超时重传次数、网络暂时不可达
7. TIME_WAIT 状态
tw_recycle = 1 时,sync timestamps 比上次小时,会被rst
7. 设置 connect_timeout
应用设置了连接超时,sync 未完成时超时了,会发送rst终止连接。
8. 非正常包
连接已经关闭,seq 不正确等
9. keepalive 超时
公网服务tcp keepalive 最好别打开;移动网络下会增加网络负担,切容易掉线;非移动网络核心ISP设备也不一定都支持keepalive,曾经也发现过广州那边有个核心节点就不支持。
10. 待整理
参考:
setsockopt :SO_LINGER 选项设置(转)
原 几种TCP连接中出现RST的情况
相关文章推荐
- 用CornerStone配置SVN,HTTP及svn简单使用说明
- GG-01224 TCP/IP error 113 (No route to host)
- tcp三次握手的过程,accept发生在三次握手哪个阶段?
- hdu 3338 网络流填数字
- 流量控制与拥塞控制
- u3d网络链接状态
- SNMP简单网络管理协议(转载)
- linux C++通过ntp协议获取网络时间
- HttpURLConnection用法详解
- TCP/TP协议的建立链接过程详述
- curl 设置自定义http头标签
- Mvc6 错误Microsoft.AspNet.Http.Features.IRequestIdentifierFeature
- http header
- Linux命令详解 -- tcpdump
- 从网络上下载文件到本地
- TCP/IP,http,socket,长连接,短连接
- UNIX网络编程卷一:第八章 I/O UDP
- Android 网络:使用URLConnection提交请求,获取html代码加载WebView
- Android AsyncHttpClient图片上传
- (4.1.28.4)HTTP协议的报文浅析