2014-03-05 110 views
3

我一直在做一個服務器。我在async方法中使用TcpListener.AcceptTcpClientAsync(),但我不知道如何真正使它工作。我現在的代碼是:接受TCP客戶端異步

private static async void StartServer() 
{ 
    Console.WriteLine("S: Server started on port {0}", WebVars.ServerPort); 
    var listener = new TcpListener(WebVars.LocalIp, WebVars.ServerPort); 
    listener.Start(); 
    var client = await listener.AcceptTcpClientAsync(); 
} 

如何處理客戶端?我是否繼續編寫代碼,它會自動創建同一方法的新線程,還是需要執行一些可以幫我實現的魔術方法?

編輯:當前代碼:

private static Task HandleClientAsync(TcpClient client) 
{ 
    var stream = client.GetStream(); 
    // do stuff 
} 
/// <summary> 
/// Method to be used on seperate thread. 
/// </summary> 
private static async void RunServerAsync() 
{ 
    while (true) 
    { 
     Console.WriteLine("S: Server started on port {0}", WebVars.ServerPort); 
     var listener = new TcpListener(WebVars.LocalIp, WebVars.ServerPort); 
     listener.Start(); 
     var client = await listener.AcceptTcpClientAsync(); 
     await HandleClientAsync(client); 
    } 
} 
+0

請不要包含關於問題標題中使用的語言的信息,除非在沒有它的情況下沒有意義。標籤用於此目的。 –

+0

這是相關的:http://stackoverflow.com/questions/21013751/what-is-the-async-await-equivalent-of-a-threadpool-server – Noseratio

回答

5

什麼都不會神奇爲您創建專用線程,雖然有用於IO的完成某些線程其中可以開始發揮作用,特別是如果你不這樣做有一個需要返回的同步上下文。

您應該決定是否希望您的StartServer方法在接受單個連接時實際完成,或者在您被告知關閉之前保持循環。

無論哪種方式,你顯然需要決定如何處理客戶端。您可以啓動一個新線程並使用同步方法,也可以使用異步IO來處理同一線程中的所有內容。例如,要輸入的數據轉儲到一個文件:

private Task HandleClientAsync(TcpClient client) 
{ 
    // Note: this uses a *synchronous* call to create the file; not ideal. 
    using (var output = File.Create("client.data")) 
    { 
     using (var input = client.GetStream()) 
     { 
      // Could use CopyToAsync... this is just demo code really. 

      byte[] buffer = new byte[8192]; 
      int bytesRead; 
      while ((bytesRead = await input.ReadAsync(buffer, 0, buffer.Length)) > 0) 
      { 
       await output.WriteAsync(buffer, 0, bytesRead); 
      } 
     } 
    } 
} 

(這是假設客戶端時,它寫完數據只會終止連接),除了從File.Create通話,這一切都是異步的 - 所以有不需要爲它創建一個單獨的線程。

這只是一個例子,當然 - 真正的連接處理通常會更復雜。如果你真正的處理需要更多的計算密集型,你可能要考慮使用Task.Run來使用線程池......這樣就不會干擾接受更多的連接。

+0

我希望服務器繼續循環。它將在while循環中,並獲取傳入的字符串,處理它,然後返回另一個字符串或文件。 – Ilan321

+0

@ Ilan321:對 - 因此您需要將'while'循環添加到您的'StartServer'方法(我將其更改爲'RunServerAsync',並使其返回一個'Task',以便任何調用它可以看到它的時間完成)。您可能還想看看我爲「引入異步」對話所寫的演示HTTP RPC處理程序:https://github.com/jskeet/DemoCode/blob/master/AsyncIntro/Code/AsyncHttpService/HttpJsonRpcHandler.cs(Not production代碼,但它可能對你有用。) –

+0

我要編輯我的問題並將當前的代碼。它會起作用嗎? – Ilan321