2011-09-07 45 views
3

背景:異步TCP System.Net.Socket發送(開始/結束髮送)實際上沒有發送任何

我一臺機器上運行的TCP服務器在不同機器上的多個客戶端連接通過TCP,和我使用Wireshark監控網絡流量,以及從我的服務器應用程序中進行記錄,並通過System.Net.Sockets中的System.Diagnostics tracelistener以詳細模式進行記錄。

問題:

提示檢查我的日誌由於一些意想不到的斷開,我看到一些很奇怪的行爲。根據服務器應用程序日誌和System.Diagnostic輸出日誌,我的服務器正在使用開始/結束髮送向客戶端發送一個4字節的數據包。 BeginSend完成,並且EndSend還完成了它說它成功發送了4字節的數據包。

但是,當我查看Wireshark日誌時,該數據包從不出現。我在服務器機器上運行Wireshark,所以應該沒有理由讓數據包出現在我的服務器和跟蹤日誌中,但不應該出現在同一臺機器上的Wireshark日誌中。

此外,在我們的服務器的EndReceive方法中由於發生SocketException而導致發送(〜30秒後)的包被發現後,發生了意外斷開連接。但在從服務器嘗試發送之間的時間內,服務器正在確認從客戶端收到的數據包,因此我知道連接仍處於活動狀態。

有沒有人有類似的經驗,或知道一個錯誤或可能會導致此問題?

我不想認爲這發生在套接字級別,其中TCP說我的數據包發送時,它甚至從來沒有把它發送到電線上,這將意味着我不能依靠TCP作爲可靠的傳輸(這當然是TCP的全部要點)。

樣本記錄

從我的服務器應用程序:

2011-09-07 10:41:38,812 Attempting to send Packet (BeginSend - 4 bytes) 
    2011-09-07 10:41:38,812 Sent Packet (EndSend - 4 bytes) 

從System.Diagnostics程序跟蹤日誌:

System.Net.Sockets Verbose: 0 : [4376] Socket#19699911::BeginSend() 
    DateTime=2011-09-07T17:41:38.8125000Z 
System.Net.Sockets Verbose: 0 : [0980] Data from Socket#19699911::PostCompletion 
    DateTime=2011-09-07T17:41:38.8125000Z 
System.Net.Sockets Verbose: 0 : [0980] 00000000 : 02 04 00 00          : .... 
    DateTime=2011-09-07T17:41:38.8125000Z 
System.Net.Sockets Verbose: 0 : [4376] Socket#19699911::EndSend(OverlappedAsyncResult#44209720) 
    DateTime=2011-09-07T17:41:38.8125000Z 
System.Net.Sockets Verbose: 0 : [4376] Exiting Socket#19699911::EndSend() -> 4#4 
    DateTime=2011-09-07T17:41:38.8125000Z 
System.Net.Sockets Verbose: 0 : [4376] Exiting Socket#19699911::BeginSend()  -> OverlappedAsyncResult#44209720 
    DateTime=2011-09-07T17:41:38.8125000Z 

我會貼Wireshark的日誌,太,但本質當時除了來自客戶端的數據包以外,該設備的接口上沒有任何註冊,而c來自服務器的響應確認。

編輯: 根據要求,這裏是發送的代碼(縮短的空間和其他原因)。很簡單,對於任何可能出錯的事情都沒有太多的方法。

在我BeginSend方法:

socket.BeginSend(data, 0, data.Length, SocketFlags.None, EndSend, state); 

在我EndSend方法:

bytesSent = socket.EndSend(ar); 

注:這不是我第一次圈地,像他們說的......我一直在寫服務器和客戶端過去15年來使用TCP套接字,並且從未經歷過這種情況。

另外,我使用的.NET版本是4.0 ......如果這是任何關係的。

幫助!我在.NET套接字編程中遇到

+0

您可以將相關的客戶端和服務器代碼添加到帖子中嗎?也許代碼中有一個錯誤。 – Jacob

+0

添加了一些代碼...但真的,沒有什麼特別的。這是一個簡單的BeginSend和EndSend ...你可以從MSDN或其他地方獲取任何示例代碼,並重現我所看到的內容。 –

+0

也許我對TCP平臺如何在.NET平臺上工作的理解是錯誤的......當一個Socket.EndSend調用在消息傳遞給接收方並且被接收方確認後會成功返回嗎?或者,當.NET將消息成功發送到網絡接口時,EndSend會成功嗎?如果是後者,一個錯誤的網絡適配器可能會解釋我所看到的。 –

回答

0

的一個問題是有關垃圾收集。我的代碼是創建一個套接字並分配給我的方法中的局部變量,而不是分配給成員變量。然後該套接字被垃圾收集,導致SocketException。顯然,做一個BeginSend不足以保存對該套接字的引用。

移動插座一個成員變量來解決這個問題對我來說。希望這與你遇到的問題有關。

+0

不幸的是,這不是問題......但該評論仍然與套接字編程有關。跨越多個線程或方法的任何套接字交互應引用一個不會像那樣收集的變量。 –

0

我不想認爲這是在插座水平上發生, 其中TCP是說,當它甚至從來沒有使它 到電線上,這將意味着我不能依靠TCP我的包被髮送作爲一個可靠的傳輸(這當然是TCP的全部要點)。

這種說法是不正確。僅僅因爲您成功寫入套接字並不意味着客戶端收到了數據,甚至離開了您的機器。這僅表示它已成功寫入內部TCP/IP緩衝區。 TCP/IP將以它認爲合適的數量或數量的塊/幀發送數據。如果您發送的數據很小,則TCP/IP將延遲嘗試將其他數據聚合到幀中,這尤其正確。

如果你沒有看到它在Wireshark的,那麼你很可能不聽正確的界面上,有一個過濾器設置,或某種形式的防火牆阻止您發送數據。查看任何有反義或其他Layere服務提供商,看看誰可以進入。

+0

我在這個界面上看到了我所有的其他數據,事實上,只有一個界面可用。我認爲我所看到的問題必須位於我的應用程序下方的某處,即Windows中的套接字層。作爲後續,當你說從.NET發送的內容僅限於內部TCP/IP緩衝區時,我不得不想知道Wireshark在哪裏執行捕獲。可能不在該級別,但可能在網絡接口實際發送數據時?如果是這種情況,那麼我真的不知道我會怎樣解決這個問題。 –

+0

Wireshark會低於tcp/ip緩衝......它會在聚合後看到數據。你確信沒有任何種類的反病毒?或者您的Wireshark捕獲過濾器處於活動狀態? – tcarvin

+1

當你說你看到來自客戶端的數據包並且他們得到了確認時,這些是否在你無法發送的同一個套接字連接上? – tcarvin

0

如果可以忽略它的限制,是否可以重寫應用程序以使用TcpClient而不是Socket?無論如何,如果你的應用綁定到TCP/IP,至少對於這個特定的套接字來說,你不妨使用抽象 - 這可能會有所幫助。此外,您可以嘗試使用EndSend(IAsyncResult, SocketError)超載來查看SocketError對象是否包含任何有用的東西。

如果沒有這些軟件調整的幫助,我不得不承認,這個問題必須低於.NET軟件水平,即在防火牆軟件(或硬件),防病毒等

0

那麼這個問題是年齡之前,所以你可能已經繼續......如果有其他人有同樣的問題,你可能想檢查Windows'Memory Pressure Protection是否可能會踢。這將導致數據包被丟棄時,有多個同時連接,這是你所看到的。

你可以嘗試另一項實驗是暫時關閉防火牆的服務器上。這也將關閉所有這些保護機制(如果我沒有弄錯),如果事情有效,那麼你知道其中一個是罪魁禍首。