【发布时间】:2013-10-11 19:04:31
【问题描述】:
我已经开始构建一个 tcp 服务器,它将能够接受许多客户端,并同时从所有客户端接收新数据。
直到现在,我都在 tcp 服务器上使用 IOCP,这非常简单和舒适, 但这次我想使用 Async / Await 技术。在 C# 5.0 中发布。
问题是,当我开始使用 async/await 编写服务器时,我发现在 tcp 多用户服务器用例中,async/await 技术。并且常规的同步方法也一样。
这是一个更具体的简单示例:
class Server
{
private TcpListener _tcpListener;
private List<TcpClient> _clients;
private bool IsStarted;
public Server(int port)
{
_tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, port));
_clients = new List<TcpClient>();
IsStarted = false;
}
public void Start()
{
IsStarted = true;
_tcpListener.Start();
Task.Run(() => StartAcceptClientsAsync());
}
public void Stop()
{
IsStarted = false;
_tcpListener.Stop();
}
private async Task StartAcceptClientsAsync()
{
while (IsStarted)
{
// ******** Note 1 ********
var acceptedClient = await _tcpListener.AcceptTcpClientAsync();
_clients.Add(acceptedClient);
IPEndPoint ipEndPoint = (IPEndPoint) acceptedClient.Client.RemoteEndPoint;
Console.WriteLine("Accepted new client! IP: {0} Port: {1}", ipEndPoint.Address, ipEndPoint.Port);
Task.Run(() => StartReadingDataFromClient(acceptedClient));
}
}
private async void StartReadingDataFromClient(TcpClient acceptedClient)
{
try
{
IPEndPoint ipEndPoint = (IPEndPoint) acceptedClient.Client.RemoteEndPoint;
while (true)
{
MemoryStream bufferStream = new MemoryStream();
// ******** Note 2 ********
byte[] buffer = new byte[1024];
int packetSize = await acceptedClient.GetStream().ReadAsync(buffer, 0, buffer.Length);
if (packetSize == 0)
{
break;
}
Console.WriteLine("Accepted new message from: IP: {0} Port: {1}\nMessage: {2}",
ipEndPoint.Address, ipEndPoint.Port, Encoding.Default.GetString(buffer));
}
}
catch (Exception)
{
}
finally
{
acceptedClient.Close();
_clients.Remove(acceptedClient);
}
}
}
现在,如果您看到“注 1”和“注 2”下的行, 它可以很容易地更改为:
注释 1 来自
var acceptedClient = await _tcpListener.AcceptTcpClientAsync();
到
var acceptedClient = _tcpListener.AcceptTcpClient();
以及来自
的注释2int packetSize = await acceptedClient.GetStream().ReadAsync(buffer, 0, 1024);
到
int packetSize = acceptedClient.GetStream().Read(buffer, 0, 1024);
而且服务器的工作方式完全相同。
那么,为什么在多个用户的 tcp 监听器中使用 async / await 和使用常规同步方法一样呢?
在这种情况下我应该继续使用 IOCP 吗?因为对我来说它非常简单和舒适,但我担心它会被淘汰,甚至在较新的 .NET 版本中不再可用。
【问题讨论】:
-
await是不同步的。特别是它不会阻塞任何线程。 -
首先,感谢您的回答。如果我在新线程(新任务)中打开接受客户端或从客户端接收数据的函数,我为什么要关心它不会阻塞任何线程?再次,就像在常规同步方法中一样。
-
@Elad 在您的用例中,没有任何区别。事实上,使用异步创建了一项不必要的任务。
-
我听说将我的代码与 async / await 一起使用需要更少的 cpu 工作 - 对吗?如果是的话,将其与 IOCP 进行比较时是否也正确?
-
@Elad:不,APM和TAP的性能基本相同; TAP 的好处是您的代码(通常)更易于维护。出于可扩展性的原因和(在一般情况下)同步 API 可能导致死锁,您确实希望对套接字使用异步方法(APM/EAP/TAP)。
标签: c# .net async-await c#-5.0 tcplistener