TCP/IP学习笔记(八)复位报文段
TCP報文首部中存在一個RST位,如果該位被置1則表示這是個復位報文段。當一個報文段從一端發往一個不存在或者處于異常狀態的另一端時,就會以一個復位報文段應答發送端,告知發送端連接出現錯誤,應當被關閉
有三種連接情況可能會產生復位報文段
- 嘗試連接到一個不存在的<ip,port>
- 主動關閉的一方的套接字設置了SO_LINGER選項,并且超時時間為0
- 另一端異常崩潰導致連接處于半關閉狀態,此時正常的一端向已關閉的一端發送報文段
向不存在的端口發送連接請求
如果客戶端嘗試連接到port端口上而這個端口根本就沒有服務器監聽,那么當客戶端發送三次握手的第一個SYN報文段時另一端會以復位報文段回應
可以在終端使用telnet ip port命令向
? ~ telnet localhost 9999 Trying 127.0.0.1... telnet: Unable to connect to remote host: Connection refused ? ~主動關閉的一方設置了SO_LINGER選項
SO_LINGER選項用于對連接關閉提供更多的控制,它影響的是close函數的行為。需要配合struct linger結構使用
struct linger {int l_onoff; // 開關選項int l_linger; // 超時時間 };使用方法為
struct linger so_linger; so_linger.l_onoff = m; so_linger.l_linger = n; ::setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger));根據上述設置的l_oneoff和l_linger不同,SO_LINGER有三種不同的行為
- l_onoff = 0,表示關閉SO_LINGER選項,調用close函數時采用默認行為,即四次揮手,close立即返回
- l_onoff != 0,l_linger = 0,表示開啟SO_LINGER選項,調用close函數時不進行四次揮手而直接發送復位報文段給對端,close立即返回
- l_onoff != 0,l_linger = 0,表示開啟SO_LINGER選項,close函數變為阻塞函數,調用時會先將發送緩沖區中的數據全部發送出去并收到對端的ACK應答報文段(或者到達超時時間)再返回close函數。并且這種情況下不管套接字是否設置非阻塞close函數都會阻塞
通過wireshark觀察報文段發送情況,客戶端服務器的行為如下
- 建立連接,客戶端設置SO_LINGER選項并設置l_onoff != 0,l_linger = 0(上述第二種情況)
- 0.5秒后客戶端調用close函數終止連接
- 服務器收到復位報文段后(read/recv返回-1)輸出錯誤信息,并調用close函數終止連接
服務器輸出錯誤信息
? server ./server Connection reset by peer復位報文段不需要對端應答,因為RST代表連接出現錯誤,雙方只要各自關閉就可以了
半關閉連接情況下發送數據
在介紹?;疃〞r器(KEEPALIVE)時提到過,如果通信雙方的一端突然崩潰,會導致連接處于半關閉狀態,也就是一端已經關閉,而另一端仍處于打開狀態。在這種情況下,如果正常的一端向已關閉的一端發送數據,由于對端已經重啟,丟失了所有連接信息,會返回一個復位報文段
借用<TCP/IP詳解>中的例子,在連接正常的情況下斷開服務器以太網電纜并重啟,隨后客戶端發送數據
觀察tcpdump結果
最終,服務器由于無法識別發來的連接,發送給客戶端復位報文段以告知對方關閉連接
總結
以上是生活随笔為你收集整理的TCP/IP学习笔记(八)复位报文段的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每天一道LeetCode-----从右向
- 下一篇: 每天一道LeetCode-----给定二