11 TCP套接字之SIGPIPE訊號

2021-09-21 12:57:47 字數 1934 閱讀 6043

前面我們解決了併發服務端的問題, 但是還是沒有解決掉客服端的bug.

我們以上一節的**為例浮現這個bug.

完整** : fork_sigchld.c

可能你已經忘了客服端的問題了, 這裡在重新說明一下 : 當建立連線後, 服務端主動關閉後, 客服端並沒有立即退出, 而是處於阻塞狀態直到有輸入才會退出.

分析問題的時, 應該先來看一下抓包的情況.

問題基本也能分析出來.

服務端關閉時向客服端傳送fin, 根據四次揮手的原則, 此時客服端還能夠向服務端傳送資料, 也就解釋了客服端沒有傳送fin而是阻塞在read函式等待輸入資料, 但服務端其實傳送fin後就被關閉了, 等待客服端傳送資料後因為對端已經完全關閉了所以傳送rst.

客服程序看不到rst, 因為在呼叫read之後立即呼叫write並且收到服務端的fin後返回0, 程序繼續阻塞在第二次的read函式.

其實當程序接收到rst的套接字執行的寫操作時, 核心會向該程序傳送sigpipe訊號. 該訊號預設行為是為了終止程序, 但是該訊號預設是被忽略的, 所以解決這個問題就需要客服端捕捉該訊號然後退出才行.

有了這個辦法接下來在客服端捕捉sigpipe訊號即可.

void

sighandler

(int signo)

}int

main()

完整** : client_sigpipe.c

服務端 :

.

/a.out 1

8080

127.0

.0.1

客服端 :

當服務端關閉後客服端阻塞直到傳送資料, 但是客服端write返回0, 然後繼續阻塞到第二次read; 當第二次read後才捕捉ret訊號呼叫捕捉函式.

最終我們成功捕捉到了ret訊號, 但實際並沒有完美的解決客服端阻塞的問題, 而且通過訊號捕捉也不是乙個很好的解決方案, 畢竟如果客服端也是多工的話捕捉就出問題的. 難道這個問題就沒有辦法很好的解決了? 別急, 在下一節分析完了就可以完美的解決了.

這裡在羅嗦一下, 涉及到與題意無關的, 但希望大家能借該例子理解一下半開啟連線的知識.

服務端(或者客服端)異常終止了連線, 而對端沒有接收到報文段, 此時對端還維持這原來的連線, 這種狀態就被稱為半開啟. 就算服務端重啟後也並不知道對端的存在, 只有對端傳送資料過來, 自己不認識會回rst, 對端才知道關閉連線.

注意: 這裡是半開啟, 與後面談到的半關閉 [1]

並不一樣.

前面通訊中關於recv引數中,flag選項 [1]

可以設定錯誤時不傳送sigpipe訊號.

TCP的套接字

摘自 深入理解計算機網路 王達著 機械工業出版社 1.ipv4資料報頭部格式 2.ipv6資料報頭部格式 3.ipv4資料報的封裝與解封裝 4.ipv4資料報的分段與重組 5.arp協議報文格式及arp表 6.arp位址解析原理 7.icmp協議及報文格式 8.ipv6協議族的其它協議 9.tcp的...

TCP套接字程式設計

網路程式設計又稱為套接字程式設計,為了與遠端計算機進行資料傳輸,需要連線到網際網路,而程式設計中的 套接字 就是用來連線該網路的工具。它本身具有連線的含義,還可以表示為兩台計算機之間的網路連線。4.呼叫accept函式受理連線請求 基於tcp的服務端 客戶端 tcp伺服器端預設函式呼叫順序 sock...

TCP套接字程式設計

對於socket不理解的可以檢視 c語言通過socket程式設計實現tcp通訊,linux socket程式設計 socket詳解 先看看程式效果圖 提示如果伺服器,直接通過ctrl z關閉,這樣程式占用的位址不會釋放,需要以下操作 1.ps 檢視程序 2.kill 9 程式pid 強制殺死程序 服...