2011-09-19 97 views
1

所以,我對多線程和套接字編程很陌生,特別是在C#中。如何每次在C#中收到新連接時創建一個新線程?

無論如何,我想創建一個程序,創建每個新的接受的TcpClient作爲一個新的線程。

這是我編:

public static void Listen() 
    { 
     try 
     { 
      listener = new TcpListener(IPAddress.Any, port); 
      listener.Start(); 

      while (true) 
      { 
       t = new Thread((client = listener.AcceptTcpClient)); 

      } 
     } 
     catch { Listen(); } 
    } 

我也已經宣佈聽者作爲的TcpListener,T爲主題,和客戶端的TcpClient的。

代碼是好的,除了我創建線程的地方,它給了我一個錯誤。

我的最終目標是爲每個接受的連接創建一個新的線程,然後能夠將數據發送到特定的連接。

那麼,如何在新線程中創建每個連接/客戶端?如何從另一個稱爲Send的方法引用特定的線程/連接(僅通過流將數據發送到特定的線程/連接)?

+0

有什麼錯誤? –

+0

-1提到一個錯誤,但沒有提供任何更多的信息。什麼是錯誤?這是一個例外嗎?它在哪裏錯誤? –

+0

它出現了多個錯誤,但它都圍繞着它而不是正確的「類型」來啓動一個新的線程。 – Alper

回答

0

這是我的socket服務器示例的啓動方法。注意新線程將新的ThreadStart作爲參數。如果需要,我可以發送更多樣本。

它使用ThreadPool.QueueUserWorkitem而不是每個請求使用一個線程。看看聽衆。

public void Start() 
    { 
     m_protocol = LoadProtocolPlugIn(); 

     // Create a TcpListener to accept client connection requests 
     TcpListener tcpListener = new TcpListener(m_address, m_port); 
     tcpListener.Start(); 

     // 
     // Create a protocol listener per thread 
     // 
     for (int i = 0; i < m_listeners; i++) 
     { 
      ProtocolListener listener = new ProtocolListener(tcpListener, m_protocol); 
      Thread thread = new Thread(new ThreadStart(listener.Start)); 
      thread.Start(); 

      Console.WriteLine("Listening on thread: {0}", thread.Name); 
     } 

     m_state = ServerState.Started; 
    } 

和這裏的協議偵聽器:

class ProtocolListener 
{ 
    TcpListener m_listener; 
    IProtocol m_protocol = null; 
    TcpClient m_client = null; 

    internal ProtocolListener(TcpListener listener, IProtocol protocol) 
    { 
     m_listener = listener; 
     m_protocol = protocol; 
    } 

    internal void Start() 
    { 
     // 
     // Block waiting for socket connection and then process. Repeat in endless loop. 
     // 
     while (true) 
     { 
      try 
      { 
       m_client = m_listener.AcceptTcpClient(); 
       ThreadPool.QueueUserWorkItem (new WaitCallback(ProcessClientProtocol), m_protocol); 
      } 
      catch (SocketException se) 
      { 
       // TODO: replace with logging and event log 
       Console.WriteLine("Exception = " + se.Message); 
      } 
     } 
    } 

    private void ProcessClientProtocol (object protocol) 
    { 
     Debug.Assert(m_client != null); 
     Debug.Assert(protocol != null); 

     ((IProtocol)protocol).Client = m_client; 
     ((IProtocol)protocol).ProcessClient(); 
    } 
} 
4

既然你提到,你是新的線程,插座,我會建議在方法上的改變。爲每個傳入連接創建一個新線程將無法很好地擴展。 1000個用戶導致1000個線程,您的服務器將花費大部分時間上下文切換。相反,您應該考慮使用異步I/O方法(例如TcpListener.BeginAcceptTcpClient)。只有在需要執行某些操作時,纔會在.NET線程池線程上調用您提供給此方法的回調。只要確保同步對實例變量的訪問(例如通過鎖定語句),因爲如果兩個客戶端同時連接,則回調可以並行運行(當然這是目標)。祝你好運。

-1

Thread構造函數接受委託,而你試圖給它的對象。 當你創建一個線程時,你需要提供一個在該線程中執行的方法。例如:

private void HandleClient(TcpClient client) 
{ 
    // ... 
} 

然而,它通常是一個壞主意,創建自己的線程。您應該使用ThreadPool或任務並行庫,如果您使用的是.NET 4:

ThreadPool.QueueUserWorkItem(() => HandleClient(acceptedClient)); 

Task.Factory.StartNew(() => HandleClient(acceptedClient)); 
相關問題