最近在做socket程式設計,wifi測試時發現距離遠了之後,拿近了後,熱點會再次連上,但程式裡的socket不會重連,後來發現問題的根源。如下
當乙個已完成的連線準備好被accept的時候,select會把監聽socket標記為可讀;因此,如果用select等待外來的連線時,應該不需要把監聽socket設定為非阻塞模式,因為如果select告訴我們連線已經就緒,accept就不應該被阻塞;
不過這樣做的時候有乙個bug:當客戶端在跟伺服器建立連線之後傳送了乙個rst包,這個時候accept就會阻塞,直到有下乙個已完成的連線準備好被accept為止.
struct linger的l_onoff標誌設為1,l_linger設為0.這個時候,如果關閉tcp連線時,會先在socket上傳送乙個rst包;這個時候會出現下面的問題:
a:select向伺服器返回監聽socket可讀,但是伺服器要在一段時間之後才能呼叫accept;
b:在伺服器從select返回和呼叫accept之前,收到從客戶傳送過來的rst;
c:這個已經完成的連線被從佇列中刪除,我們假設沒有其它已完成的連線存在;
d:伺服器呼叫accept,但是由於沒有其它已完成的連線存在,因而伺服器被阻塞了;
備註:伺服器會被一直阻塞在accept呼叫上,直到另外乙個客戶建立乙個連線為止;但是如果一直沒有其它客戶建立連線,那麼伺服器將仍然一直被阻塞在accept呼叫上,不處理任何其他已就緒的socket;
解決這個問題的辦法是:
a:如果使用select來獲知何時有鏈結已就緒可以accept時,總是把監聽socket設定為費阻塞模式,並且
b:在後面的accept呼叫中忽略以下錯誤:ewouldblock(源自berkeley的實現在客戶放棄連線時出現的錯誤)、econnaborted(posix.1g的實現在客戶放棄連線時出現的錯誤)、eproto(svr4的實現在客戶放棄連線時出現的錯誤)和eintr(如果訊號**獲).
TCP非阻塞accept和非阻塞connect
非阻塞accept 當乙個已完成的連線準備好被accept的時候,select會把監聽socket標記為可讀。因此,如果用select等待外來的連線時,應該不需要把監聽socket設定為非阻塞模式,因為如果select告訴我們連線已經就緒,accept就不應該被阻塞。不過這樣做的時候有乙個bug 當...
將ACCEPT改成非阻塞型
這個專案中寫的程式是與遠端進行socket通訊,用到accept來接受遠端的連線請求,一直以來在程式裡對accept用的都是阻塞方式,接收到乙個新的連線請求後,就建立乙個新的執行緒處理與客戶端的通訊任務。今天由於需要實現伺服器端設定客戶端心跳包週期的功能,如果每個執行緒都去查詢資料庫裡心跳包週期有沒...
關於阻塞 非阻塞 非同步 同步
阻塞 比如 recv 這個函式就是阻塞函式,只有讀到資料了才會返回 還有accept 這個函式也是阻塞函式,只有客戶端連線上來了才會返回,不然整個程式都停留在accept出現的地方阻塞著,一直等著有客戶端連線上來accept返回後才繼續執行下去。非阻塞就是和上面相反的意思。同步也就是和阻塞差不多的意...