RST情况汇总
- TCP 接收缓冲区中存在未处理的数据时关闭连接,会向对端发送RST报文。
下面进行实验验证。
//server
int main()
{
int sock_listen = socket(AF_INET, SOCK_STREAM, 0);
int recv_size = 100000;
socklen_t optlen = sizeof(recv_size);
setsockopt(sock_listen, SOL_SOCKET, SO_RCVBUF, (void*)&recv_size, optlen);
struct sockaddr_in addr_listen;
bzero(&addr_listen, sizeof(addr_listen));
addr_listen.sin_addr.s_addr = inet_addr("192.168.248.128");
addr_listen.sin_port = htons(12345);
addr_listen.sin_family = AF_INET;
Bind(sock_listen, (struct sockaddr *) &addr_listen, sizeof(addr_listen));
Listen(sock_listen, 20);
int sock_conn;
sock_conn = Accept(sock_listen, NULL, NULL);
sleep(10); //等待10秒,确保接收缓冲区已收到100000字节
close(sock_conn);//不read,直接关闭
}
//==================================
//client
int main()
{
int sock_clnt;
struct sockaddr_in addr_serv;
sock_clnt = socket(AF_INET, SOCK_STREAM, 0);
memset(&addr_serv, 0, sizeof(addr_serv));
addr_serv.sin_family = AF_INET;
addr_serv.sin_port = htons(12345);
addr_serv.sin_addr.s_addr = inet_addr("192.168.248.128");
Connect(sock_clnt, (struct sockaddr*)&addr_serv, sizeof(addr_serv));
char buf[100000] = {0};
writen(sock_clnt, buf, sizeof(buf)); //发送100000字节
while(1);
}
先后运行 server 和 client,使用 wireshark 抓包,结果如下:
直接看倒数第二项,server 回复的 ACK = 100001,说明 server 端的缓冲区已经接收了这 100000 字节,但由于没有读取(read)缓冲区就关闭(close)套接字,因此向 client 发出了 RST,即最后一项。
那么我们为 server 加上 read,读取这 100000 字节后再 close,结果如下:
这次就是标准的四次挥手啦!
- 为了避免
FIN_WAIT1
状态的连接过多,我们可以调小tcp_orphan_retries
的值,也可以通过tcp_max_orphans
限制其数量, 如果孤儿连接数量大于它,新增的孤儿连接将不再走四次挥手,而是直接发送 RST 复位报文强制关闭。 - 《UNP》P160——linger
- close 后过段时间端口彻底关闭,收到 FIN也只会回复RST
本文链接:
/archives/RST-summary
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
后端技术分享!
喜欢就支持一下吧