2010-09-08 88 views
1

我使用TcpListener和SocketClient構建了一個基本的.NET服務器 - 客戶機基礎結構。 它是多線程的和異步的。問題是,當超過30個客戶端一次連接時,服務器崩潰。.NET TCP服務器穩定性問題

我還找不到導致崩潰的原因,儘管我使用了相當多的Try-Catch塊來確保記錄所有的excepions。

所以我在想,我可能在服務器代碼的概念上做錯了什麼。我希望你們能幫我找到造成這些事故的原因。代碼如下:

啓動服務器,並偵聽連接:

public void StartServer() 
    { 
     isConnected = true; 
     listener.Start(); 
     connectionThread = new Thread(new ThreadStart(ListenForConnection)); 
     connectionThread.Start(); 
    } 

    private void ListenForConnection() 
    { 
     while (isConnected) 
     { 
      try 
      { 
       TcpClient client = listener.AcceptTcpClient(); 
       ClientConnection connection = new ClientConnection(this, client); 
       connections.Add(connection); 
      } 
      catch (Exception ex) 
      { 
       log.Log("Exception in ListenForConnection: " + ex.Message, LogType.Exception); 
      } 
     } 
    } 

的ClientConnection類:

public class ClientConnection : IClientConnection 
{ 
    private TcpClient client; 
    private ISocketServer server; 
    private byte[] data; 
    private object metaData; 

    public TcpClient TcpClient 
    { 
     get { return client; } 
    } 

    internal ClientConnection(ISocketServer server, TcpClient client) 
    { 
     this.client = client; 
     this.server = server; 

     data = new byte[client.ReceiveBufferSize]; 

     lock (client.GetStream()) 
     { 
      client.GetStream().BeginRead(data, 0, client.ReceiveBufferSize, ReceiveMessage, null); 
     } 
    } 

    internal void ReceiveMessage(IAsyncResult ar) 
    { 
     int bytesRead; 

     try 
     { 
      lock (client.GetStream()) 
      { 
       bytesRead = client.GetStream().EndRead(ar); 
      } 

      if (bytesRead < 1) 
       return; 

      byte[] toSend = new byte[bytesRead]; 
      for (int i = 0; i < bytesRead; i++) 
       toSend[i] = data[i]; 

      // Throws an Event with the data in the GUI Dispatcher Thread 
      server.ReceiveDataFromClient(this, toSend); 

      lock (client.GetStream()) 
      { 
       client.GetStream().BeginRead(data, 0, client.ReceiveBufferSize, ReceiveMessage, null); 
      } 
     } 
     catch (Exception ex) 
     { 
      Disconnect(); 
     } 
    } 

    public void Disconnect() 
    { 
     // Disconnect Client 
    } 


} 

而從服務器發送到一個數據或所有客戶端:

public void SendDataToAll(byte[] data) 
    { 
     BinaryWriter writer; 

     try 
     { 
      foreach (IClientConnection connection in connections) 
      { 
       writer = new BinaryWriter(connection.TcpClient.GetStream()); 
       writer.Write(data); 
       writer.Flush(); 
      } 
     } 
     catch (Exception ex) 
     { 
      // Log 
     } 
    } 

    public void SendDataToOne(IClientConnection client, byte[] data) 
    { 
     BinaryWriter writer; 

     try 
     { 
      writer = new BinaryWriter(client.TcpClient.GetStream()); 
      writer.Write(data); 
      writer.Flush(); 
     } 
     catch (Exception ex) 
     { 
      // Log 
     } 
    } 

在某些時候,服務器崩潰,我真的沒有起點甚至在哪裏尋找問題。如果需要,我可以提供更多的代碼。

任何幫助是非常讚賞:-) 安德烈

+0

如果您使用的是Win XP SP2,則可能是這種情況。請參閱http://forum.emule-project.net/index.php?showtopic=56016&s=9439bf4074e02abd0a66c1b7dc2d3549 – Zafer 2010-09-08 14:33:32

+0

不,其託管在Windows Server 2003上 – Andrej 2010-09-08 14:37:58

+0

您應該查看未處理的異常事件以嘗試捕獲異常:http:/ /msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx – 2010-09-08 15:45:21

回答

1

你應該訪問連接領域線程安全的。

在SendData中,您正在遍歷連接並向每個客戶端發送數據。如果一個新的客戶端在foreach循環執行時連接,你將得到一個異常,並顯示消息「Collection was modified; enumeration operation may not execute」,因爲當你迭代它時這個集合就被修改了,這是不允許的。

修改SendDataToAll行至

foreach (IClientConnection connection in connections.ToList()) 

,使問題消失(解決方案是Collection was modified; enumeration operation may not execute提供)。

+0

謝謝,看起來很有希望,我會看看是否有幫助:-) – Andrej 2010-09-09 10:12:17

+0

似乎這部分真的導致一些崩潰。不知道他們是否都走了,但這真的很有幫助。謝謝。 – Andrej 2010-09-10 13:16:56

0

ClientConnection.ReceiveMessage方法的catch塊中的Disconnect調用有可能拋出一個異常,然後該異常在catch中傳播並且未處理。

爲了確保捕獲所有異常並記錄它們,請嘗試向AppDomain.CurrentDomain.UnhandledException事件註冊一個事件處理程序。另外,如果您將服務器作爲Windows服務運行,則應用程序事件日誌中可能存在.NET異常條目。

+0

不,Disconnect中的代碼也在Try Catch塊中。 – Andrej 2010-09-09 10:11:07