標籤:style blog http color ar os for sp 資料
http://my.oschina.net/costaxu/blog/127394
在TCP協議中RST表示複位,用來異常的關閉串連,在TCP的設計中它是不可或缺的。發送RST包關閉串連時,不必等緩衝區的包都發出去,直接就丟棄緩衝區的包發送RST包。而接收端收到RST包後,也不必發送ACK包來確認。
其實在網路編程過程中,各種RST錯誤其實是比較難排查和找到原因的。下面我列出幾種會出現RST的情況。
1 連接埠未開啟
伺服器程式連接埠未開啟而用戶端來串連。這種情況是最為常見和好理解的一種了。去telnet一個未開啟的TCP的連接埠可能會出現這種錯誤。這個和作業系統的實現有關。在某些情況下,作業系統也會完全不理會這些發到未開啟連接埠請求。
比如在下面這種情況下,主機241向主機114發送一個SYN請求,表示想要串連主機114的40000連接埠,但是主機114上根本沒有開啟40000這個連接埠,於是就向主機241發送了一個RST。這種情況很常見。特別是伺服器程式core dump之後重啟之前連續出現RST的情況會經常發生。
當然在某些作業系統的主機上,未必是這樣的表現。比如向一台WINDOWS7的主機發送一個串連不存在的連接埠的請求,這台主機就不會回應。
2 請求逾時
曾經遇到過這樣一個情況:一個用戶端串連伺服器,connect返回-1並且error=EINPROGRESS。 直接telnet發現網路連接沒有問題。ping沒有出現丟包。用抓包工具查看,用戶端是在收到伺服器發出的SYN之後就莫名其妙的發送了RST。
比如像下面這樣:
有89、27兩台主機。主機89向主機27發送了一個SYN,表示希望串連8888連接埠,主機27回應了主機89一個SYN表示可以串連。但是主機27卻很不友好,莫名其妙的發送了一個RST表示我不想串連你了。
後來經過排查發現,在主機89上的程式在建立了socket之後,用setsockopt的SO_RCVTIMEO選項設定了recv的逾時時間為100ms。而我們看上面的抓包結果表示,從主機89發出SYN到接收SYN的時間多達110ms。(從15:01:27.799961到15:01:27.961886, 小數點之後的單位是微秒)。因此主機89上的程式認為接收逾時,所以發送了RST拒絕進一步發送資料。
3 提前關閉
關於TCP,我想我們在教科書裡都讀到過一句話,‘TCP是一種可靠的串連‘。 而這可靠有這樣一種含義,那就是作業系統接收到的來自TCP串連中的每一個位元組,我都會讓應用程式接收到。如果應用程式不接收怎麼辦?你猜對了,RST。
看兩段程式:
這一段是server的最簡單的代碼。邏輯很簡單,監聽一個TCP連接埠然後當有用戶端來串連的時候fork一個子進程來處理。注意看的是這一段fork裡面的處理:
?
| 123 |
char pcContent[4096]; read(real_fd,pcContent,4096); close(real_fd); |
每次只是讀socket的前4096個位元組,然後就關閉掉串連。
然後再看一下client的代碼:
?
這段代碼更簡單,就是開啟一個socket然後串連一個伺服器並發送5000個位元組。剛才我們看伺服器的代碼,每次只接收4096個位元組,那麼就是說用戶端發送的剩下的4個位元組服務端的應用程式沒有接收到,伺服器端的socket就被關閉掉,這種情況下會發生什麼狀況呢,還是抓包看一看。
前三行就是TCP的3次握手,從第四行開始看,用戶端的49660連接埠向伺服器的9877連接埠發送了5000個位元組的資料,然後伺服器端發送了一個ACK進行了確認,緊接著伺服器向用戶端發送了一個RST斷開了串連。和我們的預期一致。4 在一個已關閉的socket上收到資料
如果某個socket已經關閉,但依然收到資料也會產生RST。
代碼如下:
用戶端在服務端已經關閉掉socket之後,仍然在發送資料。這時服務端會產生RST
1 從TCP協議的原理來談談RST攻擊 http://russelltao.iteye.com/blog/1405349
2 TCP客戶-伺服器程式例子http://blog.csdn.net/youkuxiaobin/article/details/6917880
幾種TCP串連中出現RST的情況