我試圖在異步HTTP客戶端中重用套接字,但我無法第二次連接到主機。我基本上把我的異步HTTP客戶端狀態機具有以下狀態:重用異步套接字:後續連接嘗試失敗
- 可用:插座可供使用
- 連接:將插座連接到端點
- 發送:套接字發送數據到端點
- 接收:插座從端點
- 無法接收數據:有一個插座故障
- 清理:清理套接字狀態
在連接狀態下我打電話BeginConnect
:
private void BeginConnect()
{
lock (_sync) // re-entrant lock
{
IPAddress[] addersses = Dns.GetHostEntry(_asyncTask.Host).AddressList;
// Connect to any available address
IAsyncResult result = _reusableSocket.BeginConnect(addersses, _asyncTask.Port, new AsyncCallback(ConnectCallback), null);
}
}
回調方法改變狀態Sending
一次成功的連接已經建立:
private void ConnectCallback(IAsyncResult result)
{
lock (_sync) // re-entrant lock
{
try
{
_reusableSocket.EndConnect(result);
ChangeState(EClientState.Sending);
}
catch (SocketException e)
{
Console.WriteLine("Can't connect to: " + _asyncTask.Host);
Console.WriteLine("SocketException: {0} Error Code: {1}", e.Message, e.NativeErrorCode);
ThreadPool.QueueUserWorkItem(o =>
{
// An attempt was made to get the page so perform a callback
ChangeState(EClientState.Failed);
});
}
}
}
在我Shutdown
的清理插座和Disconnect
帶重用標記:
後續調用BeginConnect
結果和例外:
SocketException:連接嘗試 失敗,因爲連接的方沒有 一段 時間後沒有正確答覆或建立的連接失敗 因爲連接主機未能響應 XX.XXX.XX.XX:80
錯誤代碼:10060
下面是狀態跟蹤:
Initializing...
Change State: Connecting
Change State: Sending
Change State: Receiving
Change State: CleanUp
Callback: Received data from client 0 // <--- Received the first data
Change State: Available
Change State: Connecting // <--- Timeout when I try to reuse the socket to connect to a different endpoint
什麼我必須做的,以便能夠重新使用套接字連接到不同的主機?
注意:我有
而不是
試圖重新連接到同一主機,但
我假設
發生同樣的事情(即無法連接)。
更新
我發現下面的音符在documentation of BeginConnect:
如果此套接字之前已斷開連接,然後BeginConnect必須在一個線程,將不會退出,直到操作完成調用。這是底層提供商的限制。此外,使用的EndPoint必須不同。
我開始懷疑我的問題是否與該問題有關...我正在連接到不同的EndPoint,但它們是什麼意思,我們稱之爲BeginConnect的線程在操作完成之前不能退出?
更新2.0:
我問了related question,我嘗試使用「異步家庭」調用,而不是「開始家庭」電話,但我得到了同樣的問題!
我不知道爲什麼我沒有回答你的問題,但我做這種微型優化的原因是因爲我每秒抓取300多個網頁,每次抓取都要求我關閉舊套接字,處置它並打開一個新套接字。該應用程序運行時間很長,因此最終會導致內存抖動並降低系統速度。性能是這種情況下的關鍵。 – Kiril 2011-11-24 06:24:44