首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步TcpListener

异步TcpListener
EN

Code Review用户
提问于 2014-02-21 23:51:36
回答 1查看 7.9K关注 0票数 4

我正在尝试使用TPL实现一个TcpListener。不过,我不确定我做得对不对。我也在尽量保持代码的小。在控制台应用程序中,这一切都很好。

代码语言:javascript
复制
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喜欢这样做。)

代码语言:javascript
复制
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方法:

代码语言:javascript
复制
    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支持取消。

EN

回答 1

Code Review用户

发布于 2014-02-22 01:23:27

  1. 如果立即await所有内容,就不会得到任何并发性。这意味着,在任何时候,只能有一个连接到此侦听器。这是故意的吗?
  2. 因为TCP的工作方式,这个Connected财产可退回true即使对方已经断开了连接。这意味着您应该发送保持活动的数据包,即使您逻辑上想要做的只是阅读。
  3. 只有当您可以使用ContinueWith()时,async才是非常有用的。OnlyOnFaulted可以很容易地使用try-catch重写。虽然您应该只捕获所需的特定异常,但不是所有这些异常。因此,您的代码看起来可能如下:尝试{等待this.ReadStringAsync(this.Connection,编码,进度);} catch (NotSureWhichException ex) { progress.Report(“客户端{0}断开连接。”,Connection.TcpClient.Client.RemoteEndPoint);}
  4. 我认为你对待<End>的方式是错误的。如果每个连接总是只有一条消息,那么在阅读<End>之后,您应该以某种方式指出这一点。如果可以有多条消息,那么可以在同一个ReadAsync()中读取一条消息的结尾和下一条消息的开始,这意味着您不会报告部分消息。
票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/42480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档