2014-03-05 108 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