去你爺爺的MSDN!

本週客戶那邊出現了一個很嚴重且緊急的BUG,大致情況是,當通過.Net Framework 1.1的TcpClient連續高頻率訪問某個Socket服務器的時候,第三次或之後的連接請求就會出現超時錯誤(10060),因爲一些特殊原因,不方便在該服務器上調試,只好靠猜測、修正、驗證、猜測、修正、驗證……

原因終於是調查清楚了,Socket客戶端、服務器端的原因都有,但是主要原因還是在客戶端,發現原來是開發人員受了MSDN的誤導,在完成一次TCP訪問之後,調用TcpClient.Close之前,沒有顯式地調用NetworkStream.Close,因爲服務器端在某個時間範圍內不會主動關閉該TCP連接,並且線程數和最大連接數有限,所以導致後來的連接請求發生超時錯誤。

開發人員不顯式調用NetworkStream.Close的理由是,根據MSDN的以下記述:

http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.close(vs.71).aspx

.NET Framework Class Library 1.1
TcpClient.Close Method
Closes the TCP connection and releases all resources associated with the TcpClient.

[C#]
public void Close();

Remarks
The Close method closes the TCP connection. It calls the Dispose method passing a true value to release all managed and unmanaged resources associated with the TcpClient. These resources include the underlying Socket used for connecting with the remote host, and the NetworkStream used to send and receive data.

既然調用TcpClient.Close之後該方法裏面的處理會自行釋放NetworkStream等一切相關的託管/非託管資源,那麼就沒必要再顯式地去釋放這些資源,否則便有疊牀架屋之嫌,而且會增加無意義的代碼,引入不必要的複雜性。

但是,實際上發現,MSDN這麼說,而MS的代碼實現時卻沒有這麼做!帶着困惑和焦慮摸索了將近一個星期之後,我們找到了以下這個KB:

http://support.microsoft.com/kb/821625/en

SYMPTOMS
When you call the TcpClient Close method, you expect the underlying TCP connection to be closed as described in the "TcpClient.Close Method" topic of the .NET Framework Class Library documentation.

RESOLUTION
To resolve this problem, close the associated NetworkStream object that the TcpC...To resolve this problem, close the associated NetworkStream object that the TcpClient GetStream method returns.

根據這個KB修正了客戶端的代碼,問題自然是解決了,但是我還是忍不住罵一句:去你爺爺的MS!去你爺爺的MSDN!爲什麼,因爲對於任何一個使用微軟技術的開發人員來說,MSDN就等於Bible,我們寧願先懷疑自己,也不會先去懷疑MSDN,微軟有義務保證MSDN的正確性和權威性。

後來我們查閱了.Net Framework 2.0和3.0的API說明資料,發現同一方法的Remarks部分已經做了修正(或僅僅是2.0以後獨有的特徵?只能猜測)。

http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.close(VS.80).aspx

.NET Framework Class Library
TcpClient.Close Method
Disposes this TcpClient instance without closing the underlying connection.

C#
public void Close ()

Remarks
The Close method marks the instance as disposed but does not close the TCP connection. Calling this method does not release the NetworkStream that is used to send and receive data. You must call the Close method to close the stream and the TCP connection.

其實因爲微軟的文檔或程序BUG已經導致我們發生過很多不愉快事件了,這次簡直失望得無以復加,作爲一個主要面向微軟技術的技術工作者,心寒吶。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章