使用http 发送同一个包,sleep 20 秒后再读取数据,htpp设置1s的超时时间,超时后会关闭socket ,可是有时发送RST,有时发送FIN,如下图:
后来google 了一把,发现 tcp 的接受缓冲区的数据到 用户态,中间会有三个队列:
- receive队列是真正的接收队列,操作系统收到的TCP数据包经过检查和处理后,就会保存到这个队列中。
backlog
是“备用队列”。当socket处于用户进程的上下文时(即用户正在对socket进行系统调用,如recv),操作系统收到数据包时会将数据包保存到backlog
队列中,然后直接返回。prequeue
是“预存队列”。当socket没有正在被用户进程使用时,也就是用户进程调用了read或者recv系统调用,但是进入了睡眠状态时,操作系统直接将收到的报文保存在prequeue
中,然后返回。
正常来说 TCP 收消息过程会涉及三个队列:
backlog:
sk->sk_backlogprequeue:
tp->ucopy.prequeue- 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/
扫描二维码关注公众号,回复:
13084343 查看本文章