关闭tcp连接时有时发送FIN有时发送RST

使用http 发送同一个包,sleep 20 秒后再读取数据,htpp设置1s的超时时间,超时后会关闭socket ,可是有时发送RST,有时发送FIN,如下图:

后来google 了一把,发现 tcp 的接受缓冲区的数据到 用户态,中间会有三个队列:

  • receive队列是真正的接收队列,操作系统收到的TCP数据包经过检查和处理后,就会保存到这个队列中。
  • backlog是“备用队列”。当socket处于用户进程的上下文时(即用户正在对socket进行系统调用,如recv),操作系统收到数据包时会将数据包保存到 backlog队列中,然后直接返回。
  • prequeue是“预存队列”。当socket没有正在被用户进程使用时,也就是用户进程调用了read或者recv系统调用,但是进入了睡眠状态时,操作系统直接将收到的报文保存在 prequeue中,然后返回。

正常来说 TCP 收消息过程会涉及三个队列:

  1. backlog:  sk->sk_backlog
  2. prequeue: tp->ucopy.prequeue
  3. receive:        sk->sk_receive_queue

go程序调用send() 后,recv() 就处于阻塞状态,所以数据会进入Prequeue中,而此时由于超时时间到时,recv()没有执行完成,

有时一个消息可以全部进入Prequeue,这时缓冲区中没有数据,所以关闭时,发送的是FIN

有时不能全部进入Prequeue,这时缓冲区中还有部分数据,所以关闭是,发送的是RST; 

参考:

https://ylgrgyq.github.io/2017/08/01/linux-receive-packet-3/

https://www.cnblogs.com/chenny7/p/5067826.html

猜你喜欢

转载自blog.csdn.net/zgb40302/article/details/111213559