1.close()函數(shù)
close 一個套接字的默認(rèn)行為是把套接字標(biāo)記為已關(guān)閉,然后立即返回到調(diào)用進(jìn)程,該套接字描述符不能再由調(diào)用進(jìn)程使用,也就是說它不能再作為read或write的第一個參數(shù),然而TCP將嘗試發(fā)送已排隊等待發(fā)送到對端的任何數(shù)據(jù),發(fā)送完畢后發(fā)生的是正常的TCP連接終止序列。 在多進(jìn)程并發(fā)服務(wù)器中,父子進(jìn)程共享著套接字,套接字描述符引用計數(shù)記錄著共享著的進(jìn)程個數(shù),當(dāng)父進(jìn)程或某一子進(jìn)程close掉套接字時,描述符引用計數(shù)會相應(yīng)的減一,當(dāng)引用計數(shù)仍大于零時,這個close調(diào)用就不會引發(fā)TCP的四路握手?jǐn)噙B過程。 2.shutdown()函數(shù)
該函數(shù)的行為依賴于howto的值 1.SHUT_RD:值為0,關(guān)閉連接的讀這一半。 2.SHUT_WR:值為1,關(guān)閉連接的寫這一半。 3.SHUT_RDWR:值為2,連接的讀和寫都關(guān)閉。 終止網(wǎng)絡(luò)連接的通用方法是調(diào)用close函數(shù)。但使用shutdown能更好的控制斷連過程(使用第二個參數(shù))。 3.兩函數(shù)的區(qū)別 而shutdown會切斷進(jìn)程共享的套接字的所有連接,不管這個套接字的引用計數(shù)是否為零,那些試圖讀得進(jìn)程將會接收到EOF標(biāo)識,那些試圖寫的進(jìn)程將會檢測到SIGPIPE信號,同時可利用shutdown的第二個參數(shù)選擇斷連的方式。 下面將展示一個客戶端例子片段來說明使用close和shutdown所帶來的不同結(jié)果: 客戶端有兩個進(jìn)程,父進(jìn)程和子進(jìn)程,子進(jìn)程是在父進(jìn)程和服務(wù)器建連之后fork出來的,子進(jìn)程發(fā)送標(biāo)準(zhǔn)輸入終端鍵盤輸入數(shù)據(jù)到服務(wù)器端,知道接收到EOF標(biāo)識,父進(jìn)程則接受來自服務(wù)器端的響應(yīng)數(shù)據(jù)。
對于這段代碼,我們所期望的是子進(jìn)程獲取完標(biāo)準(zhǔn)終端的數(shù)據(jù),寫入套接字后close套接字,并退出,服務(wù)器端接收完數(shù)據(jù)檢測到EOF(表示數(shù)據(jù)已發(fā)送完),也關(guān)閉連接,并退出。接著父進(jìn)程讀取完服務(wù)器端響應(yīng)的數(shù)據(jù),并退出。然而,事實會是這樣子的嘛,其實不然!子進(jìn)程close套接字后,套接字對于父進(jìn)程來說仍然是可讀和可寫的,盡管父進(jìn)程永遠(yuǎn)都不會寫入數(shù)據(jù)。因此,此socket的斷連過程沒有發(fā)生,因此,服務(wù)器端就不會檢測到EOF標(biāo)識,會一直等待從客戶端來的數(shù)據(jù)。而此時父進(jìn)程也不會檢測到服務(wù)器端發(fā)來的EOF標(biāo)識。這樣服務(wù)器端和客戶端陷入了死鎖(deadlock)。如果用shutdown代替close,則會避免死鎖的發(fā)生。
|
|