linux accept过程,Linux协议栈accept和syn队列问题

161310 cient端收到synack后,根据ack值,使用SACK算法,只重传最后一个ack内容。

Server端收到数据包,由于accept队列仍然是满的,所以server端处理也只是标记acked,然后返回。

162884 client端等待几秒后,没有收到对应的ack,认为之前的数据包也丢失,所以重传之前的内容数据包。

Server端收到数据包,由于accept队列仍然是满的,所以server端处理也只是标记acked,然后返回。

164828 client端等待一段时间后,认为连接不可用,于是发送FIN、ACK给server端。Client端的状态变为FIN_WAIT1,等待一段时间后,client端将看不到该链接。

164829 server端收到ACK后,此时cgi程序处理完一个请求,从accept队列中取走一个连接,此时accept队列中有了空闲,server端将请求的连接放到accept队列中。

这样cgi所在的服务器上显示该链接是established的,但是nginx(client端)所在的服务器上已经没有该链接了。

之后,当cgi程序从accept队列中取到该连接后,调用read去读取sock中的内容,但是由于client端早就退出了,所以read就会block那里了。

问题解决

或许你会认为在164829中,server端不应该建立连接,这是内核的bug。但是内核是按照RFC来实现的,在3次握手的过程中,是不会判断FIN标志位的,只会处理SYN、ACK、RST这三种标志位。

从应用层的角度来考虑解决问题的方法,那就是使用非阻塞的方式read,或者使用select超时方式read;亦或者nginx中关闭连接的时候使用RST方式,而不是FIN方式。

附录1

when I use linux TCP socket, and find there is a bug in function sk_acceptq_is_full():

When a new SYN comes, TCP module first checks its validation. If valid,send SYN,ACK to the client and add the sock

to the syn hash table.

Next time if received the valid ACK for SYN,ACK from the client. server will accept this connection and increase the

sk->sk_ack_backlog -- which is done in function tcp_check_req().

We check wether acceptq is full in function tcp_v4_syn_recv_sock().

Consider an example:

After listen(sockfd, 1) system call, sk->sk_max_ack_backlog is set to

As we know, sk->sk_ack_backlog is initialized to 0. Assuming accept() system call is not invoked now

1. 1st connection comes. invoke sk_acceptq_is_full(). sk->sk_ack_backlog=0 sk->sk_max_ack_backlog=1, function return 0 accept this connection. Increase the sk->sk_ack_backlog

2. 2nd connection comes. invoke sk_acceptq_is_full(). sk->sk_ack_backlog=1 sk->sk_max_ack_backlog=1, function return 0 accept this connection. Increase the sk->sk_ack_backlog

3. 3rd connection comes. invoke sk_acceptq_is_full(). sk->sk_ack_backlog=2 sk->sk_max_ack_backlog=1, function return 1. Refuse this connection.I think it has bugs. after listen system call. sk->sk_max_ack_backlog=1

but now it can accept 2 connections.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值