1、几种TCP连接中出现RST的情况
参考:http://my.oschina.net/costaxu/blog/127394
1 端口未打开
2 请求超时:用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间
3 提前关闭:close时,接收缓冲区中还有数据(对于l_onoff=1,l_linger=0)
4 在一个已关闭的socket上收到数据:服务器端关闭socket之后,客户端继续发送数据。
2、TCP链接主动关闭不发fin包奇怪行为分析(应当只是对于l_onoff=1,l_linger=0)
引入:http://csrd.aliapp.com/?p=1055
服务器主动close时,如果服务器接收缓冲区中还有数据,协议栈就会向客户端发rst代替fin. 并且在发送RST包给对端前会调用tcp_set_state()将套接字的状态设置为TCP_CLOSE,这时没有TIME_WAIT状态,没有FIN_WAIT_1状态。所以在编写应用程序时,在关闭连接前,一定要保证所有接收到的数据被读取,否则连接会不正常关闭。
解决方法:先读完接收缓存区中的所有数据,再close。
/* prevent those nasty RST packets */
/*读完接收缓冲区中的所有数据后,再close*/
{
char buf[SQUID_TCP_SO_RCVBUF];
while (FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF) > 0);
}
3、close和shutdown
a、使用close中止一个连接,但它只是减少描述符的参考数,并不直接关闭连接,只有当描述符的参考数为0时才关闭连接。注意close的行为受到SO_LINGER选项的影响。
b、shutdown可直接关闭描述符,不考虑描述符的参考数,可选择中止一个方向的连接。在多进程中如果一个进程中shutdown(sfd, SHUT_RDWR)后其它的进程将无法进行通信.如果一个进程close(sfd)将不会影响到其它进程.
4、补充:tcp连接的终止
以下两种情况是TCP连接关闭情况的一部分,在其他情况下,内核可能给对端发送的不是FIN包,而是RST包(如前所述)。