新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > Linux協議棧accept和syn隊列問題

        Linux協議棧accept和syn隊列問題

        作者: 時間:2016-10-08 來源:網絡 收藏

        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.


        上一頁 1 2 下一頁

        關鍵詞:

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 金山区| 竹溪县| 朝阳区| 沧州市| 乌拉特前旗| 凤凰县| 高雄县| 龙里县| 泊头市| 平谷区| 牙克石市| 广饶县| 赣州市| 兴化市| 日照市| 静安区| 集贤县| 肇州县| 邯郸市| 华池县| 江达县| 白玉县| 鄂尔多斯市| 香港| 张掖市| 犍为县| 诏安县| 黑山县| 浪卡子县| 上饶市| 文安县| 临泉县| 自治县| 和林格尔县| 和硕县| 南和县| 阿克| 洞头县| 海林市| 望江县| 甘南县|