(轉載) socket:10038錯誤{winSock的一個bug:當closesocket多次錯誤使用時會導致問題}
程式原來是單執行緒網路程式,需要修改為多執行緒,修改之後,總是出問題,輔助執行緒中的recv函式總是執行一陣子之後收到長度為-1的資料報,導致程式執行不正確甚至崩潰。
由於是多執行緒,只好打日誌進行除錯,發現一個奇怪的問題。在A執行緒與B執行緒中,均使用了socket這個函式來產生socket,竟然會產生兩個相同返回值的socket!也就是說,A執行緒與B執行緒能同時獲得socket值為360的socket,這樣當A正在使用360進行資料接收時,B去連線一把,A自然就出錯了。
這個問題實在是詭異,因為socket又不是COM元件,是可以直接線上程中共享的,究竟是出了什麼問題呢,MSDN和網路上沒有見到任何與此問題相關的內容。活脫脫地就是API出錯了!按道理這是不可能的事情啊。
實在沒轍了,只好review程式碼,發現程式中有很多這樣的語句:
if( mSocket != INVALID_SOCKET )
{
closesocket( mSocket );
}
這句有什麼問題沒有?呵呵看起來沒什麼問題,但是,不容置疑的是,肯定會導致一個socket被關閉多次。本著死馬當著活馬醫的原則,進行修改,每次closesocket之後,將socket的值置為INVALID_SOCKET,執行程式,問題解決。
這個問題也太ft了,windows竟然連這個容錯都沒有做,按道理這是很好做的,socket實際上只是一個索引值,系統核心在關閉時如果發現已經關閉就不要做操作就可以了。現在看起來,核心裡面貌似是一個socket緩衝池,程式在使用的時候使用計數來管理生命週期。這樣當一個socket被關閉多次後,再建立改socket之後,系統可能會認為該socket是關閉的(因為計數小於等於0)。所以下次分配的時候,會將該索引重新分配出去。
該問題在vista home版上出現,其他平臺又沒有問題不得而知,由此可以看出成對編碼的好處以及面向物件封裝的好處。
轉自:http://blog.csdn.net/chen495810242/article/details/42029825
個人註釋:在win7上的測試結果,當一個工程呼叫多個dll的時候,不同的dll之間使用socket這個函式來產生socket,返回值是可能一樣的,就會發生連線無緣無故被斷開的現象,查了兩三天的說