我正在尝试使用TPL实现一个TcpListener。不过,我不确定我做得对不对。我也在尽量保持代码的小。在控制台应用程序中,这一切都很好。
public async Task RunAsync(CancellationToken cancellationToken)
{
var listener = new TcpListener(ip, port);
listener.Start();
while (!cancellationToken.IsCancellationRequested)
{
await AcceptClientAsync(listener, encoding, progress, cancellationToken);
}
listener.Stop();
}下面是AcceptClientAsync方法:(对不起,格式设置很奇怪。StyleCop喜欢这样做。)
private async Task AcceptClientAsync(TcpListener tcpListener, Encoding encoding, IProgress<string> progress, CancellationToken cancellationToken)
{
var client = await tcpListener.AcceptTcpClientAsync();
this.Connection = new ConnectionState { TcpClient = client };
while (client.Connected && !cancellationToken.IsCancellationRequested)
{
await
this.ReadStringAsync(this.Connection, encoding, progress)
.ContinueWith(
task =>
progress.Report(
string.Format("Client {0} disconnected.", Connection.TcpClient.Client.RemoteEndPoint)),
TaskContinuationOptions.OnlyOnFaulted);
}
}ReadStringAsync方法:
private async Task ReadStringAsync(ConnectionState connection, Encoding encoding, IProgress<string> progress)
{
var stream = connection.TcpClient.GetStream();
if (connection.Read > 0)
{
var encoded = encoding.GetString(connection.Buffer, 0, connection.Read);
connection.StringBuilder.Append(encoded);
}
var decoded = connection.StringBuilder.ToString();
if (decoded.Contains("<End>"))
{
progress.Report(decoded.Replace("<End>", string.Empty));
}
connection.Read = await stream.ReadAsync(connection.Buffer, 0, connection.Buffer.Length);
}我还想继续使用IProgress<>界面,并通过CancellationTokens支持取消。
发布于 2014-02-22 01:23:27
await所有内容,就不会得到任何并发性。这意味着,在任何时候,只能有一个连接到此侦听器。这是故意的吗?Connected财产可退回true即使对方已经断开了连接。这意味着您应该发送保持活动的数据包,即使您逻辑上想要做的只是阅读。ContinueWith()时,async才是非常有用的。OnlyOnFaulted可以很容易地使用try-catch重写。虽然您应该只捕获所需的特定异常,但不是所有这些异常。因此,您的代码看起来可能如下:尝试{等待this.ReadStringAsync(this.Connection,编码,进度);} catch (NotSureWhichException ex) { progress.Report(“客户端{0}断开连接。”,Connection.TcpClient.Client.RemoteEndPoint);}<End>的方式是错误的。如果每个连接总是只有一条消息,那么在阅读<End>之后,您应该以某种方式指出这一点。如果可以有多条消息,那么可以在同一个ReadAsync()中读取一条消息的结尾和下一条消息的开始,这意味着您不会报告部分消息。https://codereview.stackexchange.com/questions/42480
复制相似问题