2012-12-23 28 views
0

位停留在此,我...套接字 - 你可以把它另一個線程?

場景:

套接字處理遊戲模擬器來發送和接收的VL64和其他字符串編碼的編碼數據。需要支持約4000套接字請求等

目前它使用的AsyncCallback來執行異步服務器角色等

代碼:

private static SnowTcpListener mServer; 

mServer = new SnowTcpListener(new IPEndPoint(IPAddress.Any, "IP"), backlog, new OnNewConnectionCallback(SessionManager.HandleIncomingConnection)); 

積壓套接字積壓INT。

SnowTcpListener

/// <summary> 
    /// Callback to be invoked upon accepting a new connection. 
    /// </summary> 
    /// <param name="Socket">Incoming socket connection</param> 
    public delegate void OnNewConnectionCallback(Socket Socket); 

    /// <summary> 
    /// Reality simple asynchronous TCP listener. 
    /// </summary> 
    public class SnowTcpListener : IDisposable // Snow prefix to avoid conflicts with System.Net.TcpListener 
    { 
     private Socket mSocket; 
     private OnNewConnectionCallback mCallback; 

     public SnowTcpListener(IPEndPoint LocalEndpoint, int Backlog, OnNewConnectionCallback Callback) 
     { 
      mCallback = Callback; 

      mSocket = new Socket(LocalEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 
      mSocket.Bind(LocalEndpoint); 
      mSocket.Listen(Backlog); 

      BeginAccept(); 
     } 

     public void Dispose() 
     { 
      if (mSocket != null) 
      { 
       mSocket.Dispose(); 
       mSocket = null; 
      } 
     } 

     private void BeginAccept() 
     { 
      try 
      { 
       mSocket.BeginAccept(OnAccept, mSocket); 
      } 
      catch (Exception) { } 
     } 

     private void OnAccept(IAsyncResult Result) 
     { 
      try 
      { 
       Socket ResultSocket = (Socket)mSocket.EndAccept(Result); 
       mCallback.Invoke(ResultSocket); 
      } 
      catch (Exception) { } 

      BeginAccept(); 
     } 

SessionManager.HandleIncomingConnection:

public static void HandleIncomingConnection(Socket IncomingSocket) 
     { 
      bool Reject = ModerationBanManager.IsRemoteAddressBlacklisted(IncomingSocket.RemoteEndPoint.ToString().Split(':')[0]); 

      Output.WriteLine((Reject ? "Rejected" : "Accepted") + " incoming connection from " + IncomingSocket.RemoteEndPoint.ToString() + ".", 
       OutputLevel.Informational); 

      if (Reject) 
      { 
       try 
       { 
        IncomingSocket.Close(); 
       } 
       catch (Exception) { } 

       return; 
      } 

      lock (mSyncRoot) 
      { 
       uint Id = mCounter++; 
       mSessions.Add(Id, new Session(Id, IncomingSocket)); 
      } 
     } 

然後它會創建一個新的 「會話」

public Session(uint Id, Socket Socket) 
{ 
    mId = Id; 
    mSocket = Socket; 
    mBuffer = new byte[512]; 
    mPongOk = true; 

    mSocket.SendBufferSize = 512; 

    BeginReceive(); 
} 

其中依次調用BeginRecieve()

private void BeginReceive() 
     { 
      try 
      { 
       if (mSocket != null) 
       { 
        //TODO: BeginRecieve(); 
        mSocket.BeginReceive(mBuffer, 0, mBuffer.Length, SocketFlags.None, new AsyncCallback(OnReceiveData), mSocket); 
       } 
      } 
      catch (Exception) 
      { 
       SessionManager.StopSession(mId); 
      } 
     } 

OnRecieveData()

private void OnReceiveData(IAsyncResult Result) 
     { 
      int ByteCount = 0; 

      try 
      { 
       if (mSocket != null) 
       { 
        ByteCount = mSocket.EndReceive(Result); 
       } 
      } 
      catch (Exception) { } 

      if (ByteCount < 1 || ByteCount >= mBuffer.Length) 
      { 
       SessionManager.StopSession(mId); 
       return; 
      } 

      ProcessData(ByteUtil.ChompBytes(mBuffer, 0, ByteCount)); 
      BeginReceive(); 
     } 

如果您需要了代碼,只是問。

我將如何去創造它,因此連接是在一個單獨的線程,或者我怎麼會提高我的插座經驗,都拿到一定數額的會話,它只是落後了。我試圖增加緩衝區,但它使情況變得更糟。

我已經走到了我的束縛的盡頭,我嘗試了幾乎所有我能想到的,我真的可以做一些幫助!

感謝您閱讀這篇很長的文章,如果問題不明確,請嘗試使它更清晰!

乾杯 邁克

回答

1

你做了什麼來評估現有的代碼中的瓶頸和性能問題?你有沒有使用任何工具分析它?

從發佈到目前爲止的代碼中,您只是保持異步接收新連接(BeginAccept)和傳入數據(BeginReceive)。這些都不會造成任何有辱人格的表現。但是,BeginReceive函數調用「ProcessData」,這大​​概是您的所有業務邏輯都用於處理消息的地方。我懷疑這是你的瓶頸所在。但這只是一個猜測。

你說4000套接字,所以「每個連接線程」聽起來不像正確的設計。

但是既然你已經在做異步套接字,那麼正確的做法似乎是在工作池線程中調用ProcessData。當ProcessData完成時,只需再次在該會話對象上調用BeginReceive。類似如下:

private void OnReceiveData(IAsyncResult Result) 
{ 
    int ByteCount = 0; 
    try 
    { 
     if (mSocket != null) 
     { 
      ByteCount = mSocket.EndReceive(Result); 
     } 
    } 
    catch (Exception) { } 

    if (ByteCount < 1 || ByteCount >= mBuffer.Length) 
    { 
     SessionManager.StopSession(mId); 
     return; 
    } 

    ThreadPool.QueueUserWorkItem(ProcessDataInThread, ByteCount); 

} 

void ProcessDataInThread(object context) 
{ 
    int ByteCount = (int)context; 

    ProcessData(ByteUtil.ChompBytes(mBuffer, 0, ByteCount)); 
    BeginReceive(); 
} 
+0

這是輝煌的,它工作出色! – x06265616e

相關問題