2012-04-12 65 views
0

我有一個用C#編寫的多線程TCP服務器。客戶端被服務器接受,並且在連接時不會離開服務器。經過大約1300次活動連接後,我的軟件出現System.OutOfMemmoryException錯誤。這個問題是否與32位系統架構和RAM有關?我有32位Windows 7專業版和4 GB內存。當我的服務器上存在大約1300個活動連接時,我的內存使用量約爲2.1GB,CPU使用率爲30%。TCP服務器中的C#System.OutOfMemmoryException

謝謝。

+1

我猜...是的,無論如何,你的應用程序在32位體系結構上看不到超過2 GB的內存。 – 2012-04-12 12:06:47

+0

你有一個線程每個連接或你使用線程池? – Nick 2012-04-12 12:08:14

+0

我知道他有第一個。 – AgentFire 2012-04-12 12:11:09

回答

5

System.OutOfMemmoryException當您的進程中創建了~1300個線程時(在32位操作系統上)時拋出。問題是你正在爲每個連接創建全新的線程。這是不好的做法。

您應該改爲只使用一個線程來管理髮送數據,使用同一個線程(或可能是第二個)來發送數據,並且只能使用一個來接受連接。線程池接受所有客戶

代碼例如:一個線程接受所有客戶

TcpListener tcpListener = new TcpListener(IPAddress.Any, 90); 

public void BeginAccept() 
{ 
    try { tcpListener.BeginAcceptTcpClient(AcceptClient, null); } 
    catch { /* Swallowing is bad */ } 
} 

private void AcceptClient(IAsyncResult ar) 
{ 
    TcpClient tcpClient; 

    try { tcpClient = tcpListener.EndAcceptTcpClient(ar); } 
    catch { /* Swallowing is bad */ } 
    finally { BeginAccept(); } 

    // TODO: Add your brand new tcpClient to some sort of collection, may be. 
} 

代碼示例:

TcpListener tcpListener = new TcpListener(IPAddress.Any, 90); 
bool isListening; 

public void BeginAccept() 
{ 
    while (isListening) 
    { 
     TcpClient tcpClient; 

     try { tcpClient = tcpListener.AcceptTcpClient(); } 
     catch { /* Swallowing is bad */ } 

     // TODO: Add your brand new tcpClient to some sort of collection, may be. 
    } 
} 
+1

啊,我只是想提到線程!我認爲默認堆棧大小是1mb – Nick 2012-04-12 12:09:27

+0

我認爲這是不可能的,因爲我想打開每個設備的線程。我如何使用線程池? – sanchop22 2012-04-12 12:24:15

+0

我認爲一切皆有可能。爲每個設備保留線程的原因是什麼? – AgentFire 2012-04-12 13:01:19

0

你應該看看貫徹Asynchronous Server Socket
我仍然建議在不同的線程中發送響應以避免隊列/ TCP重發。
您可以使用任務,也可以將收到的消息與相關連接添加到併發隊列中,並由工作人員處理它們。

0

您的計算機/操作系統不是限制因素。它可以爲每個進程分配近4GB(如果總共使用4GB以上,它將開始交換/寫入磁盤:這比普通內存慢得多,但仍然可以工作)。 但是,C#編譯器正在限制您。 C#默認編譯32位,這意味着每個進程只能使用大約2GB的內存。這就是爲什麼你的服務器一旦達到2GB就會崩潰。 你可以編譯一個64位的操作系統,它可以讓你使用幾乎無限的內存,但是你沒有64位的操作系統,所以它不會在你的機器上運行。

最好爲每個客戶端連接而不是線程創建一個新進程。你的主進程會監聽和接受連接,當一個新的連接產生時,它應該產生一個專門用於處理與該客戶端的連接的新進程。因爲每個連接都有自己的進程,所以你不會再達到2GB的限制,並且還有很多優點:一旦連接關閉,回收內存就容易得多,並且一個連接中的任何錯誤都不太可能導致整個程序崩潰。 當然,多進程體系結構的編程比多線程編程要困難一些,因爲沒有共享內存,但這是更好的方法。