當前位置:首頁 > 公眾號精選 > CPP開發(fā)者
[導讀]近期遇到一個問題,簡單點說,主機A上顯示一條ESTABLISHED狀態(tài)的TCP連接到主機B,而主機B上卻沒有任何關(guān)于主機A的連接信息,經(jīng)查明,這是由于主機A和主機B的發(fā)送/接收緩沖區(qū)差異巨大,導致主機B進程退出后,主機A暫時憋住,主機B頻繁發(fā)送零窗口探測,F(xiàn)IN_WAIT1狀態(tài)超...



近期遇到一個問題,簡單點說,主機A上顯示一條ESTABLISHED狀態(tài)的TCP連接到主機B,而主機B上卻沒有任何關(guān)于主機A的連接信息,經(jīng)查明,這是由于主機A和主機B的發(fā)送/接收緩沖區(qū)差異巨大,導致主機B進程退出后,主機A暫時憋住,主機B頻繁發(fā)送零窗口探測,FIN_WAIT1狀態(tài)超時,進而連接被銷毀,然而主機A并不知情導致。

正好昨天也有人咨詢另外一個類似的問題,那么就抽昨晚和今天早上的時間,寫一篇總結(jié)吧。

TCP處處是坑!

不要覺得你對TCP的實現(xiàn)的代碼爛熟于心了就能把控它的所有行為!不知道你有沒有發(fā)現(xiàn),目前市面上新上市的關(guān)于Linux內(nèi)核協(xié)議棧的書可謂是汗牛充棟,然而無論作者是國內(nèi)的還是國外,幾乎都是碰到TCP就草草略過,反而對IP,ARP,DNS這些大書特書,Why?因為Linux內(nèi)核里TCP的代碼太亂太復雜了,很少有人能看明白80%以上的,即便真的有看過的,其中還包括只懂代碼而不懂網(wǎng)絡技術(shù)的,我就發(fā)現(xiàn)很多聲稱自己精通Linux內(nèi)核TCP/IP源碼,結(jié)果竟然不知道什么是默認路由…


所以我打算寫一篇文章,趁著這個FIN_WAIT1問題,順便表達一下我是如何學習網(wǎng)絡技術(shù),我是如何解決網(wǎng)絡問題的方法論觀點,都是形而上,個人看法:

  • 設(shè)計覆蓋全面的復現(xiàn)實驗

  • 通讀協(xié)議標準文檔,理解實現(xiàn)建議

  • 再次實驗,預測并確認問題以外的現(xiàn)象

  • 核對代碼實現(xiàn),跟蹤代碼的Changelog

  • 寫一個自己的實現(xiàn)或者亂改代碼


本文聊聊TCP的FIN_WAIT1以及TCP假連接(死連接)問題。先看FIN_WAIT1。

首先還是從狀態(tài)機入手,看看和FIN_WAIT1相關(guān)的狀態(tài)機轉(zhuǎn)換圖:

我們只考慮常規(guī)的從ESTABLISHED狀態(tài)的轉(zhuǎn)換,很簡單的一個單一狀態(tài)轉(zhuǎn)換:

  • ESTAB狀態(tài)發(fā)送FIN即切換到FIN_WAIT1狀態(tài);

  • FIN_WAIT1狀態(tài)下收到針對FIN的ACK即可離開FIN_WAIT1到達FIN_WAIT2.

看一下和上述狀態(tài)機轉(zhuǎn)換相關(guān)的簡單時序圖:

從狀態(tài)圖和時序圖上,我們很明確地可以看到,FIN_WAIT1持續(xù)1個RTT左右的時間!這個時間段幾乎不會被肉眼觀察到,轉(zhuǎn)瞬而即逝。


然而,這是真的嗎?


我們之所以得到FIN_WAIT1持續(xù)1個RTT這個結(jié)論,基于兩個假設(shè),即:
TCP的對端是一個正常的TCP端;兩端TCP之間的鏈路是正常的,可達的。OK,接下來我們來設(shè)計一個實驗模擬異常的情況。準備實驗拓撲如下:


host1和host2的系統(tǒng)內(nèi)核版本(uname -r獲取):

3.10.0-862.2.3.el7.x86_64
首先,我們看一下如果對端TCP針對FIN發(fā)送的ACK丟失,會發(fā)生什么。按照上述的時序圖,正常應該是FIN_WAIT1將會永久持續(xù)。我們來驗證一下。
實驗1:模擬ACK丟失在host1上做以下命令:

nc -l -p 1234
host2上完成以下命令:

cat /dev/zero|nc 1.1.1.1 1234
以上保證了host1和host2之間的TCP建立并且連接之間有持續(xù)的數(shù)據(jù)傳輸。接下來,在host2上執(zhí)行下列動作:

iptables -A INPUT -p tcp --tcp-flags ACK,FIN ACK
killall nc
此時在host2上:

[root@localhost?~]#?netstat??-antp|grep?1234
tcp????????0???1229?1.1.1.2:39318???????????????1.1.1.1:1234????????????????FIN_WAIT1???-
連續(xù)上翻命令,這個FIN_WAIT1均不會消失,暫時符合我們的預期…出去抽根煙,刷會兒微博…回來后,發(fā)現(xiàn)這個FIN_WAIT1消失了!


它是如何消失的呢?這個時候,我們提取netstat數(shù)據(jù),執(zhí)行“ netstat -st”,會發(fā)現(xiàn):

TcpExt:
...
1 connections aborted due to timeout

多了一條timeout連接!

我這里直接說答案吧。
雖然說在協(xié)議上規(guī)范上看,TCP沒有必要為鏈路或者說對端的不合常規(guī)的行為而買單,但是從現(xiàn)實角度,TCP的實現(xiàn)必須處理異常情況,TCP的實現(xiàn)必然要有所限制!

我們知道,計算機是無法處理無限,無窮這種抽線的數(shù)學概念的,所有如果針對FIN的ACK遲遲不來,那么必然要有一個等待的極限,這個極限在Linux內(nèi)核協(xié)議棧中由以下參數(shù)控制:

net.ipv4.tcp_orphan_retries?#?默認值是0!這里有坑...
這個參數(shù)表示如果一直都收不到針對FIN的ACK,那么在徹底銷毀這個FIN_WAIT1的連接前,等待幾輪RTO退避


所謂的orphan tcp connection,意思就是說,在Linux進程層面,創(chuàng)建該連接的進程已經(jīng)退出銷毀了,然而在TCP協(xié)議層面,它依然在遵循TCP狀態(tài)機的轉(zhuǎn)換規(guī)則存在著。


注意,這個參數(shù)不是一個時間量,而是一個次數(shù)量。我們知道,TCP每一次超時,都會對下一次超時時間進行指數(shù)退避,這里的次數(shù)量就是要經(jīng)過幾次退避的時間。舉一個例子,如果RTO是2ms,而tcp_orphan_retries 的值是4,那么所計算出的FIN_WAIT1容忍時間就是:T=21 22 23 24T=21 22 23 24還是看看Linux內(nèi)核文檔怎么說的吧:

tcp_orphan_retries?-?INTEGER
??This?value?influences?the?timeout?of?a?locally?closed?TCP?connec??tion,?when?RTO?retransmissions?remain?unacknowledged.
??See?tcp_retries2?for?more?details.
??The?default?value?is?8.
??If?your?machine?is?a?loaded?WEB?server,
??you?should?think?about?lowering?this?value,?such?sockets
??may?consume?significant?resources.?Cf.?tcp_max_orphans.
讓我們看看tcp_retries2,以獲取數(shù)值的含義:

tcp_retries2?-?INTEGER
??This?value?influences?the?timeout?of?an?alive?TCP?connection,
??when?RTO?retransmissions?remain?unacknowledged.
??Given?a?value?of?N,?a?hypothetical?TCP?connection?following
??exponential?backoff?with?an?initial?RTO?of?TCP_RTO_MIN?would
??retransmit?N?times?before?killing?the?connection?at?the?(N 1)th?RTO.
??The?default?value?of?15?yields?a?hypothetical?timeout?of?924.6
??seconds?and?is?a?lower?bound?for?the?effective?timeout.
??TCP?will?effectively?time?out?at?the?first?RTO?which?exceeds?the?hypothetical?timeout.
??RFC?1122?recommends?at?least?100?seconds?for?the?timeout,
??which?corresponds?to?a?value?of?at?least?8.
雖然說文檔上默認值的建議是8,但是大多數(shù)的Linux發(fā)行版上其默認值都是0。更多詳情,就自己看RFC和Linux源碼吧。


有了這個參數(shù)保底,我們知道,即便是ACK永遠不來,F(xiàn)IN_WAIT1狀態(tài)也不會一直持續(xù)下去的,這有效避免了有針對性截獲ACK或者不發(fā)送ACK而導致的DDoS,退一萬步講,即便是沒有DDoS,這種做法也具有資源利用率的容錯性,使得資源使用更加高效。


實驗1的結(jié)論如下:

  • 如果主動斷開端調(diào)用了close關(guān)掉了進程,它會進入FIN_WAIT1狀態(tài),此時如果它再也收不到ACK,無論是針對pending在發(fā)送緩沖的數(shù)據(jù)還是FIN,它都會嘗試重新發(fā)送,在收到ACK前會嘗試N次退避,該N由tcp_orphan_retries參數(shù)控制。
接下來,我們來看一個更加復雜一點的問題,還是先從實驗說起。
實驗2:模擬對端TCP不收數(shù)據(jù),接收窗口憋死在host1上做以下命令:# 模擬小接收緩存,使得憋住接收窗口更加容易

sysctl -w net.ipv4.tcp_rmem="16 32 32"
nc?-l?-p?1234
host2上完成以下命令:

cat /dev/zero|nc 1.1.1.1 1234
sleep 5 # 稍微等一下
killall nc
此時,我們發(fā)現(xiàn)host2的TCP連接進入了FIN_WAIT1狀態(tài)。然而抓包看的話,數(shù)據(jù)傳輸依然在進行:

05:15:51.674630?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[P.],?seq?305:321,?ack?1,?win?5840,?options?[nop,nop,TS?val?1210945?ecr?238593370],?length?16
05:15:51.674690?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?321,?win?0,?options?[nop,nop,TS?val?238593471?ecr?1210945],?length?0
05:15:51.674759?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?321,?win?16,?options?[nop,nop,TS?val?238593471?ecr?1210945],?length?0
05:15:51.777774?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[P.],?seq?321:325,?ack?1,?win?5840,?options?[nop,nop,TS?val?1211048?ecr?238593471],?length?4
05:15:51.777874?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?325,?win?16,?options?[nop,nop,TS?val?238593497?ecr?1211048],?length?0
05:15:52.182918?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[P.],?seq?325:341,?ack?1,?win?5840,?options?[nop,nop,TS?val?1211453?ecr?238593497],?length?16
05:15:52.182970?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?341,?win?0,?options?[nop,nop,TS?val?238593599?ecr?1211453],?length?0
05:15:52.183055?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?341,?win?16,?options?[nop,nop,TS?val?238593599?ecr?1211453],?length?0
05:15:52.592759?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[P.],?seq?341:357,?ack?1,?win?5840,?options?[nop,nop,TS?val?1211863?ecr?238593599],?length?16
05:15:52.592813?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?357,?win?0,?options?[nop,nop,TS?val?238593701?ecr?1211863],?length?0
05:15:52.592871?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?357,?win?16,?options?[nop,nop,TS?val?238593701?ecr?1211863],?length?0
05:15:52.695160?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[P.],?seq?357:361,?ack?1,?win?5840,?options?[nop,nop,TS?val?1211965?ecr?238593701],?length?4
05:15:52.695276?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?361,?win?16,?options?[nop,nop,TS?val?238593727?ecr?1211965],?length?0
05:15:53.099612?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[P.],?seq?361:377,?ack?1,?win?5840,?options?[nop,nop,TS?val?1212370?ecr?238593727],?length?16
05:15:53.099641?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?377,?win?0,?options?[nop,nop,TS?val?238593828?ecr?1212370],?length?0
05:15:53.099671?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?377,?win?16,?options?[nop,nop,TS?val?238593828?ecr?1212370],?length?0
05:15:53.505028?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[P.],?seq?377:393,?ack?1,?win?5840,?options?[nop,nop,TS?val?1212775?ecr?238593828],?length?16
05:15:53.505081?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?393,?win?0,?options?[nop,nop,TS?val?238593929?ecr?1212775],?length?0
05:15:53.505138?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?393,?win?16,?options?[nop,nop,TS?val?238593929?ecr?1212775],?length?0
05:15:53.605923?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[P.],?seq?393:397,?ack?1,?win?5840,?options?[nop,nop,TS?val?1212876?ecr?238593929],?length?4
這是顯然的,這是因為收發(fā)兩端巨大的緩存大小差異造成的,即便是host2發(fā)送端進程退出了,在退出前已經(jīng)有大量數(shù)據(jù)pending到了TCP的發(fā)送緩沖區(qū)里面而脫離已經(jīng)被銷毀的進程了,F(xiàn)IN包當然是排在了緩沖區(qū)的末尾了。


TCP的狀態(tài)機運行在緩存的上層,即只要把FIN包pending排隊,就切換到了FIN_WAIT1,而不是說實際發(fā)送了FIN包才切換。


因此,我們可有的等了,數(shù)據(jù)傳輸依然在正常有序進行,針對小包的ACK源源不斷從host1回來,這進一步促進host2發(fā)送未竟的數(shù)據(jù)包,直到所有緩沖區(qū)的數(shù)據(jù)全部發(fā)送完畢…


不管怎樣,總是有個頭兒,只要有結(jié)束,就不需要擔心。我們可以簡單得出一個結(jié)論:

  • 如果主動斷開端調(diào)用了close關(guān)掉了進程,它會進入FIN_WAIT1狀態(tài),如果接收端的接收窗口呈現(xiàn)打開狀態(tài),此時它的TCP發(fā)送隊列中的數(shù)據(jù)包還是會像正常一樣發(fā)往接收端,直到發(fā)送完,最后發(fā)送FIN包,收到FIN包ACK后進入FIN_WAIT2。
現(xiàn)在,我們進行實驗的下一步,把host1上的接收進程nc的接收邏輯徹底憋死。很簡單,host1上執(zhí)行下面的命令即可:

killall -STOP nc
進程并沒有退出,只是暫停了,nc進程上下文的recv不再執(zhí)行,然而軟中斷上下文的TCP協(xié)議的處理依然在進行。


這個時候,抓包就會發(fā)現(xiàn)只剩下指數(shù)時間退避的零窗口探測包了:

#?注意觀察探測包發(fā)送時間的間隔
05:15:56.444570?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[.],?ack?1,?win?5840,?options?[nop,nop,TS?val?1215715?ecr?238594487],?length?0
05:15:56.444602?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?465,?win?0,?options?[nop,nop,TS?val?238594664?ecr?1214601],?length?0
05:15:57.757217?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[.],?ack?1,?win?5840,?options?[nop,nop,TS?val?1217027?ecr?238594664],?length?0
05:15:57.757248?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?465,?win?0,?options?[nop,nop,TS?val?238594992?ecr?1214601],?length?0
05:16:00.283259?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[.],?ack?1,?win?5840,?options?[nop,nop,TS?val?1219552?ecr?238594992],?length?0
05:16:00.283483?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?465,?win?0,?options?[nop,nop,TS?val?238595624?ecr?1214601],?length?0
05:16:05.234277?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[.],?ack?1,?win?5840,?options?[nop,nop,TS?val?1224503?ecr?238595624],?length?0
05:16:05.234305?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?465,?win?0,?options?[nop,nop,TS?val?238596861?ecr?1214601],?length?0
05:16:15.032486?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[.],?ack?1,?win?5840,?options?[nop,nop,TS?val?1234301?ecr?238596861],?length?0
05:16:15.032532?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?465,?win?0,?options?[nop,nop,TS?val?238599311?ecr?1214601],?length?0
05:16:34.629137?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[.],?ack?1,?win?5840,?options?[nop,nop,TS?val?1253794?ecr?238599311],?length?0
05:16:34.629164?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?465,?win?0,?options?[nop,nop,TS?val?238604210?ecr?1214601],?length?0
05:17:13.757815?IP?1.1.1.2.39318?>?1.1.1.1.1234:?Flags?[.],?ack?1,?win?5840,?options?[nop,nop,TS?val?1292784?ecr?238604210],?length?0
05:17:13.757863?IP?1.1.1.1.1234?>?1.1.1.2.39318:?Flags?[.],?ack?465,?win?0,?options?[nop,nop,TS?val?238613992?ecr?1214601],?length?0
這個實驗的現(xiàn)象和實驗1的現(xiàn)象,僅有一個區(qū)別,那就是實驗1是阻塞了ACK,而本實驗則是FIN根本就還沒有發(fā)送出去就進入了FIN_WAIT1,且針對RTO指數(shù)時間退避發(fā)送的零窗口探測的ACK持續(xù)到來,簡單總結(jié)就是:實驗1沒有ACK到來,實驗2有ACK到來。


在實驗結(jié)果之前,我們來看一段摘錄,來自RFC1122:https://tools.ietf.org/html/rfc1122#page-92

4.2.2.17?Probing?Zero?Windows:?RFC-793?Section?3.7,?page?42
.
??Probing?of?zero?(offered)?windows?MUST?be?supported.
.
??A?TCP?MAY?keep?its?offered?receive?window?closed
???indefinitely.?As?long?as?the?receiving?TCP?continues?to
??send?acknowledgments?in?response?to?the?probe?segments,?the
??sending?TCP?MUST?allow?the?connection?to?stay?open.
緊接著后面是一段注解:

DISCUSSION:
??It?is?extremely?important?to?remember?that?ACK
??(acknowledgment)?segments?that?contain?no?data?are?not
??reliably?transmitted?by?TCP.?If?zero?window?probing?is
??not?supported,?a?connection?may?hang?forever?when?an
??ACK?segment?that?re-opens?the?window?is?lost.
.
??The?delay?in?opening?a?zero?window?generally?occurs
??when?the?receiving?application?stops?taking?data?from
??its?TCP.?For?example,?consider?a?printer?daemon
??application,?stopped?because?the?printer?ran?out?of
??paper.
只要有ACK到來,連接就要保持,這會帶來什么問題呢?確實會帶來問題,但是在正視這些問題之前,Linux內(nèi)核協(xié)議棧的實現(xiàn)者,也保持了緘默,我們來看一段實驗主機host1和host2所用的標準內(nèi)核主線版本3.10的內(nèi)核源碼,來自tcp_probe_timer函數(shù)內(nèi)部的注釋以及一小段代碼:

/*?*WARNING*?RFC?1122?forbids?this
?????*
?????*?It?doesn't?AFAIK,?because?we?kill?the?retransmit?timer?-AK
?????*
?????*?FIXME:?We?ought?not?to?do?it,?Solaris?2.5?actually?has?fixing
?????*?this?behaviour?in?Solaris?down?as?a?bug?fix.?[AC]
?????*
?????*?Let?me?to?explain.?icsk_probes_out?is?zeroed?by?incoming?ACKs
?????*?even?if?they?advertise?zero?window.?Hence,?connection?is?killed?only
?????*?if?we?received?no?ACKs?for?normal?connection?timeout.?It?is?not?killed
?????*?only?because?window?stays?zero?for?some?time,?window?may?be?zero
?????*?until?armageddon?and?even?later.?We?are?in?full?accordance
?????*?with?RFCs,?only?probe?timer?combines?both?retransmission?timeout
?????*?and?probe?timeout?in?one?bottle.?????????????--ANK
?????*/

?????...
????????max_probes?=?sysctl_tcp_retries2;


if?(sock_flag(sk,?SOCK_DEAD))?{?//?如果是orphan連接的話
const?int?alive?=?((icsk->icsk_rto?<icsk_backoff)?//?即獲取tcp_orphan_retries參數(shù),有微調(diào),請詳審。本實驗參數(shù)默認值取0!
????????max_probes?=?tcp_orphan_retries(sk,?alive);


if?(tcp_out_of_resources(sk,?alive?||?icsk->icsk_probes_out?<=?max_probes))
return;
????}
//?只有在icsk_probes_out,即未應答的probe次數(shù)超過探測最大容忍次數(shù)后,才會出錯清理連接。
if?(icsk->icsk_probes_out?>?max_probes)?{
????????tcp_write_err(sk);
????}?else?{
/*?Only?send?another?probe?if?we?didn't?close?things?up.?*/
????????tcp_send_probe0(sk);
????}
是的,從上面那一段注釋,我們看出了抱怨,一個FIN_WAIT1的連接可能會等到世界終結(jié)日之后,然而我們卻只能“in full accordance with RFCs”!


這也許暗示了某種魔咒般的結(jié)果,即FIN_WAIT1將會一直持續(xù)到終結(jié)世界的大決戰(zhàn)之日。然而非也,你會發(fā)現(xiàn)大概在發(fā)送了9個零窗口探測包之后,連接就消失了。netstat -st的結(jié)果中,呈現(xiàn):

connections aborted due to timeout
看來想制造點事端,并非想象般容易!


如上所述,我展示了標準主線的Linux 3.10內(nèi)核的tcp_probe_timer函數(shù),現(xiàn)在的問題是,為什么下面的條件被滿足了呢?

if?(icsk->icsk_probes_out?>?max_probes)
只有當這個條件被滿足,tcp_write_err才會被調(diào)用,進而:

tcp_done(sk);
//?遞增計數(shù),即netstat?-st中的那條“1?connections?aborted?due?to?timeout”
NET_INC_STATS_BH(sock_net(sk),?LINUX_MIB_TCPABORTONTIMEOUT);
按照注釋和代碼的確認,只要收到ACK,icsk_probes_out 字段就將被清零,這是很明確的啊,我們在tcp_ack函數(shù)中便可看到無條件清零icsk_probes_out的動作:

static?int?tcp_ack(struct?sock?*sk,?const?struct?sk_buff?*skb,?int?flag)
{
????...
????sk->sk_err_soft?=?0;
????icsk->icsk_probes_out?=?0;
????tp->rcv_tstamp?=?tcp_time_stamp;
????...
}
從代碼上看,只要零窗口探測持續(xù)發(fā)送,不管退避到多久(最大TCP_RTO_MAX),只要對端會有ACK回來,icsk_probes_out 就會被清零,上述的條件就不會被滿足,連接就會一直在FIN_WAIT1狀態(tài),而從我們抓包看,確實是零窗口探測有去必有回的!

預期會永遠僵在FIN_WAIT1狀態(tài)的連接在一段時間后竟然銷毀了。沒有符合預期,到底發(fā)生了呢?


如果我們看高版本4.14版的Linux內(nèi)核,同樣是tcp_probe_timer函數(shù),我們會看到一些不一樣的代碼和注釋:

static?void?tcp_probe_timer(struct?sock?*sk)
{
...
/* RFC 1122 4.2.2.17 requires the sender to stay open indefinitely as
* long as the receiver continues to respond probes. We support this by
* default and reset icsk_probes_out with incoming ACKs. But if the
* socket is orphaned or the user specifies TCP_USER_TIMEOUT, we
* kill the socket when the retry count and the time exceeds the
* corresponding system limit. We also implement similar policy when
* we use RTO to probe window in tcp_retransmit_timer().
*/
start_ts = tcp_skb_timestamp(tcp_send_head(sk));
if (!start_ts)
tcp_send_head(sk)->skb_mstamp = tp->tcp_mstamp;
else if (icsk->icsk_user_timeout
本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉