RST報文詳解

2021-10-04 20:04:27 字數 2180 閱讀 9360

我們知道tcp建立連線的時候需要三次連線,tcp釋放連線的時候需要四次揮手,在這個過程中,出現了很多特殊的標誌報文段,例如syn ack fin,在tcp協議中,除了上面說了那些標誌報文段之外,還有其他的報文段,如push標誌報文段以及今天需要重點講解的rst報文段。

rst:(reset the connection)用於復位因某種原因引起出現的錯誤連線,也用來拒絕非法資料和請求。如果接收到rst位時候,通常發生了某些錯誤;

傳送rst包關閉連線時,不必等緩衝區的包都發出去,直接就丟棄緩衝區中的包,傳送rst;接收端收到rst包後,也不必傳送ack包來確認。

客戶端發起三次握手,傳送完第乙個syn分節之後,收到來自伺服器的rst分節(個人理解,分節就是報文段?)。

rst分節的內容:如果收到的是ack報文,rst取ack報文的ack序列號為rst報文的seq;如果報文不是ack報文,rst的seq為0且ack欄位為收到的報文seq+報文長度;

乙個客戶端連線伺服器,connect返回-1並且error=einprogress。 直接telnet發現網路連線沒有問題。ping沒有出現丟包。用抓包工具檢視,客戶端是在收到伺服器發出的syn之後就莫名其妙的傳送了rst。

這是為什麼呢? 

原因就是請求超時了。

有89、27兩台主機。主機89向主機27傳送了乙個syn,表示希望連線8888埠,主機27回應了主機89乙個syn表示可以連線。但是主機27卻很不友好,莫名其妙的傳送了乙個rst表示我不想連線你了。

後來經過排查發現,在主機27上的程式在建立了socket之後,用setsockopt的so_rcvtimeo選項設定了recv的超時時間為100ms。而我們看上面的抓包結果表示,從主機89發出syn到接收syn的時間多達110ms。(從15:01:27.799961到15:01:27.961886, 小數點之後的單位是微秒)。因此主機27上的程式認為接收超時,所以傳送了rst拒絕進一步接收資料。

作業系統接收到的來自tcp連線中的每乙個位元組,我都會讓應用程式接收到。如果應用程式不接收怎麼辦?傳送rst。

開啟乙個socket然後連線乙個伺服器並傳送5000個位元組。剛才我們看伺服器的**,每次只接收4096個位元組,那麼就是說客戶端傳送的剩下的4個位元組服務端的應用程式沒有接收到,伺服器端的socket就被關閉掉,這種情況下會發生什麼狀況呢,還是抓包看一看。

前三行就是tcp的3次握手,從第四行開始看,客戶端的49660埠向伺服器的9877埠傳送了5000個位元組的資料,然後伺服器端傳送了乙個ack進行了確認,緊接著伺服器向客戶端傳送了乙個rst斷開了連線。

如果想提前關閉乙個連線,就需要傳送rst報文段。

假設server和client 已經建立了連線,server呼叫了close(socket.close()方法的語義和tcp的「fin」標誌語義不一樣:傳送tcp的「fin」標誌表示我不再傳送資料了,而socket.close()表示我不在傳送也不接受資料了。) 傳送fin 段給client,此時server不能再通過socket傳送和接收資料,此時client呼叫read,如果接收到fin 段會返回0,但client此時還是可以write 給server的,write呼叫只負責把資料交給tcp傳送緩衝區就可以成功返回了,所以不會出錯,而server收到資料後應答乙個rst段,表示伺服器已經不能接收資料,連線重置,client收到rst段後無法立刻通知應用層,只把這個狀態儲存在tcp協議層。**如果client再次呼叫write發資料給server,由於tcp協議層已經處於rst狀態了,因此不會將資料發出,而是發乙個sigpipe訊號給應用層,sigpipe訊號的預設處理動作是終止程式。 

當乙個程序向某個已收到rst的套接字執行寫操作時,(此時寫操作返回epipe錯誤)核心向該程序傳送乙個sigpipe訊號,該訊號的預設行為是終止程序,因此程序必須捕獲它以免不情願地被終止;**

tcp接收到乙個根本不存在的連線上的分節;伺服器主機崩潰後重啟:它的tcp丟失了崩潰前的所有連線資訊,因此伺服器tcp對於所有收到的來自客戶的資料分節響應乙個rst;

總結出現rst報文的場景:

1.connect乙個不存在的埠;

2.向乙個已經關掉的連線send資料;

3.向乙個已經崩潰的對端傳送資料(連線之前已經被建立);

4.close(sockfd)時,直接丟棄接收緩衝區未讀取的資料,並給對方發乙個rst。這個是由so_linger選項來控制的;

5.a重啟,收到b的保活探針,a發rst,通知b。

傳送RST報文

file main.c author bearice created on 2009年12月31日,下午12 36 include stdio.h include stdlib.h include sys ioctl.h include sys types.h include sys socket....

多次RST以及不同場景下的RST報文的差異

在某個tcp互動過程中,我們發現在互動的後期,客戶端多次向伺服器端傳送rst報文,如下圖所示 我們首先來看客戶端發出的第乙個rst報文的解碼 rst與ack標誌位都置一了,並且具有ack number,非常明顯,這個報文在釋放tcp連線的同時,完成了對前面已接收報文的確認。我們再來看看客戶端發出的後...

多次RST以及不同場景下的RST報文的差異

在某個tcp互動過程中,我們發現在互動的後期,客戶端多次向伺服器端傳送rst報文,如下圖所示 我們首先來看客戶端發出的第乙個rst報文的解碼 rst與ack標誌位都置一了,並且具有ack number,非常明顯,這個報文在釋放tcp連線的同時,完成了對前面已接收報文的確認。我們再來看看客戶端發出的後...