<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > Linux協(xié)議棧accept和syn隊列問題

          Linux協(xié)議棧accept和syn隊列問題

          作者: 時間:2016-10-08 來源:網(wǎng)絡(luò) 收藏

          環(huán)境:

          本文引用地址:http://www.ex-cimer.com/article/201610/305659.htm

          Client 通過tcp 連接server,server端只是listen,但是不調(diào)用accept。通過netstat –ant查看兩端的連接情況。

          server端listen,不調(diào)用accept。

          client一直去connect server。

          問題:

          運行一段時間后,為什么server端的ESTABLISHED連接的個數(shù)基本是固定的129個,但是client端的ESTABLISHED連接的個數(shù)卻在不斷增加?

          分析

          Linux內(nèi)核協(xié)議棧為一個tcp連接管理使用兩個隊列,一個是半鏈接隊列(用來保存處于SYN_SENT和SYN_RECV狀態(tài)的請求),一個是accpetd隊列(用來保存處于established狀態(tài),但是應(yīng)用層沒有調(diào)用accept取走的請求)。

          第一個隊列的長度是/proc/sys/net/ipv4/tcp_max_syn_backlog,默認是1024。如果開啟了syncookies,那么基本上沒有限制。

          第二個隊列的長度是/proc/sys/net/core/somaxconn,默認是128,表示最多有129個established鏈接等待accept。(為什么是129?詳見下面的附錄1)。

          現(xiàn)在假設(shè)acceptd隊列已經(jīng)達到129的情況:

          client發(fā)送syn到server。client(SYN_SENT),server(SYN_RECV)

          server端處理流程:tcp_v4_do_rcv--->tcp_rcv_state_process--->tcp_v4_conn_request

          if(sk_acceptq_is_full(sk) inet_csk_reqsk_queue_yong(sk)>1)

          goto drop;

          inet_csk_reqsk_queue_yong(sk)的含義是請求隊列中有多少個握手過程中沒有重傳過的段。

          在第一次的時候,之前的握手過程都沒有重傳過,所以這個syn包server端會直接drop掉,之后client會重傳syn,當inet_csk_reqsk_queue_yong(sk) 1,那么這個syn被server端接受。server會回復(fù)synack給client。這樣一來兩邊的狀態(tài)就變?yōu)閏lient(ESTABLISHED), server(SYN_SENT)

          Client收到synack后回復(fù)ack給server。

          server端處理流程: tcp_check_req--->syn_recv_sock-->tcp_v4_syn_recv_sock

          if(sk_acceptq_is_full(sk)

          goto exit_overflow;

          如果server端設(shè)置了sysctl_tcp_abort_on_overflow,那么server會發(fā)送rst給client,并刪除掉這個鏈接;否則server端只是記錄一下LINUX_MIB_LISTENOVERFLOWS(詳見附錄2),然后返回。默認情況下是不會設(shè)置的,server端只是標記連接請求塊的acked標志,之后連接建立定時器,會遍歷半連接表,重新發(fā)送synack,重復(fù)上面的過程(具體的函數(shù)是inet_csk_reqsk_queue_prune),如果重傳次數(shù)超過synack重傳的閥值(/proc/sys/net/ipv4/tcp_synack_retries),會把該連接從半連接鏈表中刪除。

          一次異常問題分析

          Nginx通過FASTCGI協(xié)議連接cgi程序,出現(xiàn)cgi程序read讀取socket內(nèi)容的時候永遠block。通過netstat查看,cgi程序所在的服務(wù)器上顯示連接存在,但是nginx所在的服務(wù)器上顯示不存在該連接。

          下面是原始數(shù)據(jù)圖:

          我們從上面的數(shù)據(jù)流來分析一下:

          出現(xiàn)問題的時候,cgi程序(tcp server端)處理非常慢,導(dǎo)致大量的連接請求放到accept隊列,把accept隊列阻塞。

          148021 nginx(tcp client端) 連接cgi程序,發(fā)送syn

          此時server端accpet隊列已滿,并且inet_csk_reqsk_queue_yong(sk) > 1,server端直接丟棄該數(shù)據(jù)包

          148840 client端等待3秒后,重傳SYN

          此時server端狀態(tài)與之前送變化,仍然丟棄該數(shù)據(jù)包

          150163 client端又等待6秒后,重傳SYN

          此時server端accept隊列仍然是滿的,但是存在了重傳握手的連接請求,server端接受連接請求,并發(fā)送synack給client端(150164)

          150166 client端收到synack,標記本地連接為ESTABLISHED狀態(tài),給server端應(yīng)答ack,connect系統(tǒng)調(diào)用完成。

          Server收到ack后,嘗試將連接放到accept隊列,但是因為accept隊列已滿,所以只是標記連接為acked,并不會將連接移動到accept隊列中,也不會為連接分配sendbuf和recvbuf等資源。

          150167 client端的應(yīng)用程序,檢測到connect系統(tǒng)調(diào)用完成,開始向該連接發(fā)送數(shù)據(jù)。

          Server端收到數(shù)據(jù)包,由于acept隊列仍然是滿的,所以server端處理也只是標記acked,然后返回。

          150225 client端由于沒有收到剛才發(fā)送數(shù)據(jù)的ack,所以會重傳剛才的數(shù)據(jù)包

          150296 同上

          150496 同上

          150920 同上

          151112 server端連接建立定時器生效,遍歷半連接鏈表,發(fā)現(xiàn)剛才acked的連接,重新發(fā)送synack給client端。

          151113 client端收到synack后,根據(jù)ack值,使用SACK算法,只重傳最后一個ack內(nèi)容。

          Server端收到數(shù)據(jù)包,由于accept隊列仍然是滿的,所以server端處理也只是標記acked,然后返回。

          151896 client端等待3秒后,沒有收到對應(yīng)的ack,認為之前的數(shù)據(jù)包也丟失,所以重傳之前的內(nèi)容數(shù)據(jù)包。

          152579 server端連接建立定時器生效,遍歷半連接鏈表,發(fā)現(xiàn)剛才acked的連接,synack重傳次數(shù)在閥值以內(nèi),重新發(fā)送synack給client端。

          152581 cient端收到synack后,根據(jù)ack值,使用SACK算法,只重傳最后一個ack內(nèi)容。

          Server端收到數(shù)據(jù)包,由于accept隊列仍然是滿的,所以server端處理也只是標記acked,然后返回

          153455 client端等待3秒后,沒有收到對應(yīng)的ack,認為之前的數(shù)據(jù)包也丟失,所以重傳之前的內(nèi)容數(shù)據(jù)包。

          155399 server端連接建立定時器生效,遍歷半連接鏈表,發(fā)現(xiàn)剛才acked的連接,synack重傳次數(shù)在閥值以內(nèi),重新發(fā)送synack給client端。

          155400 cient端收到synack后,根據(jù)ack值,使用SACK算法,只重傳最后一個ack內(nèi)容。

          Server端收到數(shù)據(jù)包,由于accept隊列仍然是滿的,所以server端處理也只是標記acked,然后返回。

          156468 client端等待幾秒后,沒有收到對應(yīng)的ack,認為之前的數(shù)據(jù)包也丟失,所以重傳之前的內(nèi)容數(shù)據(jù)包。

          161309 server端連接建立定時器生效,遍歷半連接鏈表,發(fā)現(xiàn)剛才acked的連接,synack重傳次數(shù)在閥值以內(nèi),重新發(fā)送synack給client端。


          上一頁 1 2 下一頁

          關(guān)鍵詞:

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();