日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

【翻译】TCP backlog在Linux中的工作原理

發布時間:2025/5/22 linux 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【翻译】TCP backlog在Linux中的工作原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文How TCP backlog works in Linux
水平有限,難免有錯,歡迎指出!
以下為翻譯:


當應用程序通過系統調用listen將一個套接字(socket)置為LISTEN狀態時,需要為該套接字指定一個backlog參數,該參數通常被描述為用來限制進來的連接隊列長度(queue of incoming connections)。

由于TCP協議的三次握手機制,一個進來的套接字連接在進入ESTABLISHED狀態并且可以被accept調用返回給應用程序之前,會經歷中間狀態SYN RECEIVED(見上圖)。這意味著TCP協議棧可以有兩種方案來實現backlog隊列:

  • 只使用一個隊列,隊列大小由系統調用listen的backlog參數指定。服務端收到一個SYN數據包后將返回一個SYN/ACK數據包,同時將該連接放入到隊列中。當服務端再次收到客戶端返回的ACK時,該連接狀態將變為ESTABLISHED,從而有資格被交給應用程序處理。
  • 使用兩個隊列,一個SYN隊列和一個accept隊列。處于SYN RECEIVED狀態的連接會被添加到SYN隊列中,等到后續收到ACK變為ESTABLISHED狀態后,該連接會被轉移到accept隊列中。顧名思義,在這種實現方式下,accept系統調用可以簡單地實現為從accept隊列中消費連接,此時listen調用的backlog參數決定的是accept隊列的大小。
  • 歷史上,BCD派生的TCP實現采用第一種方案,這意味著當隊列大小達到backlog最大值時,系統將不再發送用以響應SYN數據包的SYN/ACK數據包。通常,TCP實現將簡單地丟棄收到的SYN數據包(而不是發送RST數據包)以便客戶端重試。這也是W. Richard Stevens的經典教科書《TCP/IP詳解 卷三》14.5節listen Backlog Queue中所描述的方案。

    需要注意的是,W. Richard Stevens解釋說BSD的實現實際上確實是使用兩個單獨的隊列,但是它們表現為一個單個隊列,其最大長度固定且由(但不是必須完全等于)backlog參數確定,即BSD邏輯上如方案1所述。

    Linux上的情況有些不同,listen的man手冊寫到:

    The behavior of the backlog argument on TCP sockets changed with Linux 2.2. Now it specifies the queue length forcompletely established sockets waiting to be accepted, instead of the number of incomplete connection requests. The maximum length of the queue for incomplete sockets can be set using /proc/sys/net/ipv4/tcp_max_syn_backlog
    TCP套接字上的backlog參數的行為隨Linux 2.2而改變。 現在它指等待被接受(accept)的、完全建立的套接字的隊列長度,而不是不完整的連接請求數。 不完整套接字隊列的最大長度可以通過/proc/sys/net/ipv4/tcp_max_syn_backlog設置

    這意味著當前Linux版本采用的是具有兩個不同隊列的方案二:一個SYN隊列,大小由系統范圍的設置指定;一個accept隊列,大小由應用程序指定。 方案2一個有趣的問題是,如果當前accept隊列已滿,而一個連接需要從SYN隊列中移到accept隊列中,這個時候TCP實現將如何處理?這種情況由net/ipv4/tcp_minisocks.c中的tcp_check_req函數處理。 相關代碼如下:

    child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL); if (child == NULL) goto listen_overflow;

    對于IPV4,第一行代碼實際會調用net/ipv4/tcp_ipv4.c中的tcp_v4_syn_recv_sock,其中包含如下代碼:

    if (sk_acceptq_is_full(sk))goto exit_overflow;

    上面的代碼中可以看到對accept隊列的檢查。exit_overflow標簽之后的代碼將執行一些清理工作,更新/proc/net/netstat中的ListenOverflows和ListenDrops統計信息,然后返回NULL,這將觸發執行tcp_check_req中的listen_overflow代碼:

    listen_overflow:if (!sysctl_tcp_abort_on_overflow) {inet_rsk(req)->acked = 1;return NULL;}

    這意味著除非/proc/sys/net/ipv4/tcp_abort_on_overflow設置為1(這種情況下將如代碼所示發送RST數據包),否則TCP實現基本上不做任何事情!

    總而言之,如果Linux中的(服務端)TCP實現接收到(客戶端)三次握手的ACK數據包,并且accept隊列已滿,則(服務端)基本上將忽略該數據包。這種處理方式剛聽起來可能有點奇怪,但是請記住,SYN RECEIVED狀態有一個關聯定時器:如果服務端沒有收到ACK(或者像這里所說的被忽略),則TCP實現將重新發送 SYN/ACK數據包(重試次數由/proc/sys /net/ipv4/tcp_synack_retries指定,并使用指數退避算法)。

    上述現象可以在以下數據包跟蹤中看到,客戶端嘗試連接(并發送數據)到已達到其最大backlog的套接字:

    0.000 127.0.0.1 -> 127.0.0.1 TCP 74 53302 > 9999 [SYN] Seq=0 Len=0
    0.000 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0
    0.000 127.0.0.1 -> 127.0.0.1 TCP 66 53302 > 9999 [ACK] Seq=1 Ack=1 Len=0
    0.000 127.0.0.1 -> 127.0.0.1 TCP 71 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5
    0.207 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5
    0.623 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5
    1.199 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0
    1.199 127.0.0.1 -> 127.0.0.1 TCP 66 [TCP Dup ACK 6#1] 53302 > 9999 [ACK] Seq=6 Ack=1 Len=0
    1.455 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5
    3.123 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5
    3.399 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0
    3.399 127.0.0.1 -> 127.0.0.1 TCP 66 [TCP Dup ACK 10#1] 53302 > 9999 [ACK] Seq=6 Ack=1 Len=0
    6.459 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5
    7.599 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0
    7.599 127.0.0.1 -> 127.0.0.1 TCP 66 [TCP Dup ACK 13#1] 53302 > 9999 [ACK] Seq=6 Ack=1 Len=0
    13.131 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5
    15.599 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0
    15.599 127.0.0.1 -> 127.0.0.1 TCP 66 [TCP Dup ACK 16#1] 53302 > 9999 [ACK] Seq=6 Ack=1 Len=0
    26.491 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5
    31.599 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0
    31.599 127.0.0.1 -> 127.0.0.1 TCP 66 [TCP Dup ACK 19#1] 53302 > 9999 [ACK] Seq=6 Ack=1 Len=0
    53.179 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5
    106.491 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5
    106.491 127.0.0.1 -> 127.0.0.1 TCP 54 9999 > 53302 [RST] Seq=1 Len=0

    客戶端TCP實現由于收到多個SYN/ACK數據包,會假定其發送的ACK數據包丟失,從而重新發送ACK(參見上述跟蹤中的TCP Dup ACK行)。
    如果服務器端的應用程序在達到SYN/ACK最大重試次數之前減少了backlog(即從accept隊列中消耗了一個條目),則TCP實現最終將會處理一個客戶端重復發送的ACK,將連接狀態從SYN RECEIVED轉換到ESTABLISHED,并將連接添加到accept隊列。否則的話,客戶端最終會收到一個RST數據包(如上圖所示)。

    數據包跟蹤同時也展示了上述行為另一個有趣的一面。從客戶端的角度來說,TCP連接將在收到第一個SYN/ACK數據包之后變為ESTABLISHED狀態。如果客戶端向服務端發送數據(不等待來自服務端的數據),則該數據也會被重傳。幸運的是,TCP的慢啟動可以限制重傳階段發送的數據段個數。

    另一方面,如果客戶端一直在等待來自服務端的數據,而服務端的backlog一直沒有降低,則最終的結果是客戶端的連接狀態是ESTABLISHED,而服務端的連接狀態則是SYN_RCVD(注:原文說的是CLOSED狀態,應該是不對的),也就是處于一個半連接的狀態!

    還有另一個方面我們目前沒有討論。listen的man手冊引用表明,除非SYN隊列已滿,否則每個SYN數據包都將導致TCP連接被添加到SYN隊列中,這種說法和實際情況有所出入,原因在于net/ipv4/tcp_ipv4.c中的tcp_v4_conn_request函數存在以下一段代碼:

    /* Accept backlog is full. If we have already queued enough * of warm entries in syn queue, drop request. It is better than * clogging syn queue with openreqs with exponentially increasing * timeout. */ if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); goto drop; }

    上面的代碼意味著,如果當前accept隊列已滿,內核會對接收SYN數據包的速率施加限制。如果收到太多SYN數據包其中一些將會被丟棄,這將導致客戶端重試發送SYN數據包,從而最終得到與BSD派生實現中相同的行為。

    最后看看為什么Linux的設計選擇會優于傳統的BSD實現。 Stevens提出了以下有趣的觀點:

    The backlog can be reached if the completed connection queue fills (i.e., the server process or the server host is so busy that the process cannot call accept fast enough to take the completed entries off the queue) or if the incomplete connection queue fills. The latter is the problem that HTTP servers face, when the round-trip time between the client and server is long, compared to the arrival rate of new connection requests, because a new SYN occupies an entry on this queue for one round-trip time. […]
    The completed connection queue is almost always empty because when an entry is placed on this queue, the server’s call to accept returns, and the server takes the completed connection off the queue.

    Stevens提出的解決方案只是增加backlog。這樣做的問題在于它假定如果應用程序希望調整backlog,不僅要考慮如何處理新建立的傳入連接,還有考慮諸如往返時間等流量特性。Linux中的實現有效地分離了這兩個問題:應用程序只負責調整backlog,使其可以足夠快地接收(accept)連接,避免填滿accept隊列; 系統管理員則可以根據流量特性調整/proc/sys/net/ipv4/tcp_max_syn_backlog

    轉載于:https://www.cnblogs.com/sduzh/p/6654225.html

    總結

    以上是生活随笔為你收集整理的【翻译】TCP backlog在Linux中的工作原理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 传媒av在线 | 美女黄视频在线观看 | 国产一区二区视频在线观看 | 国产福利精品视频 | 91插插影库| 麻豆av一区二区 | 影音先锋毛片 | 欧洲色网站 | 欧洲做受高潮免费看 | 亚洲色鬼 | 丝袜熟女一区二区三区 | 熟睡侵犯の奶水授乳在线 | 天天碰天天碰 | 日韩精品tv| 国产一区二区成人 | 亚洲视频久久久 | 亚洲久久成人 | 久久国产毛片 | 欧美日韩免费观看视频 | 亚洲精品天堂在线 | 国产初高中真实精品视频 | 亚洲熟女乱色综合亚洲av | 狠狠操女人 | 免费在线性爱视频 | 国产又粗又猛又色 | 精品欧美久久久 | 国产第20页 | 91精品国产综合久久久密臀九色 | 欧美成人高清 | 免费观看成人 | 欧美视频日韩视频 | 色婷婷91| 成人亚洲| 久久综合九色综合欧美狠狠 | 男受被做哭激烈娇喘gv视频 | 丰满大肥婆肥奶大屁股 | 国产日韩精品中文字无码 | 久色精品| 欧美自偷自拍 | 蜜臀aⅴ免费一区二区 | 噼里啪啦动漫高清在线观看 | 啪啪福利社 | 四虎色| 久久久久一 | 色婷婷激情综合 | 国产在线自 | 日本一区二区免费在线观看 | 日韩av电影手机在线观看 | 欧美 日韩 国产 精品 | 亚洲视频久久久 | 中文字幕一区二区三区在线观看 | 成人三级在线播放 | 国产原创视频在线 | 一级片a级片 | 亚洲区一 | 波多野结衣网址 | 国产一区二区免费在线观看 | 色噜噜在线观看 | 久久亚洲AV无码精品 | 成人羞羞网站 | va在线看| 国产精品一区二区三区不卡 | 双性人bbww欧美双性 | 美女a视频 | 日本久久一区 | 中文字幕av一区二区三区谷原希美 | 在线看欧美 | 青青插| 国产区免费观看 | 久久人人添人人爽添人人片 | 麻豆影视在线观看 | 国产精品久久久久久网站 | 乱日视频 | 麻豆av一区 | 国产精品久久久久久久久久久久 | 久久免费的精品国产v∧ | 亚洲一区二区在线免费观看 | 爱操av | 海角社区id | 亚洲精品一区二三区不卡 | 人人爽夜夜爽 | 成人免费精品视频 | 91在线短视频 | 国产69熟 | 天天干天天摸 | 久操视频免费观看 | 欧美片 | 国产性生活 | 欧美亚洲另类视频 | 这里只有精品6 | 国产a级一级片 | 男人在线网站 | 日韩精品午夜 | 蜜桃在线一区二区 | 丰满岳乱妇一区二区 | 亚洲精品久久久久久 | 国产草草浮力影院 | 好吊色在线观看 | 欧美人与动牲交xxxxbbbb |