加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 使用异步/等待的异步TcpListener的正确方法

发布时间:2020-12-15 18:03:33 所属栏目:百科 来源:网络整理
导读:我一直在思考通过使用异步编程设置TCP服务器的正确方法. 通常我会在每个传入的请求中产生一个线程,但是我想做大部分的ThreadPool,所以当连接空闲时,没有被阻塞的线程. 首先,我将创建监听器并开始接受客户端,在这种情况下,在控制台应用程序中: static void M
我一直在思考通过使用异步编程设置TCP服务器的正确方法.

通常我会在每个传入的请求中产生一个线程,但是我想做大部分的ThreadPool,所以当连接空闲时,没有被阻塞的线程.

首先,我将创建监听器并开始接受客户端,在这种情况下,在控制台应用程序中:

static void Main(string[] args)
{
    CancellationTokenSource cancellation = new CancellationTokenSource();
    var endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"),8001);
    TcpListener server = new TcpListener(endpoint); 

    server.Start();
    var task = AcceptTcpClients(server,cancellation.Token);

    Console.ReadKey(true);
    cancellation.Cancel();
    await task;
    Console.ReadKey(true);
}

在这种方法中,我会循环接受传入的请求并产生一个新的Task来处理连接,所以循环可以重新接受更多的客户端:

static async Task AcceptTcpClients(TcpListener server,CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        var ws = await server.AcceptTcpClientAsync();

        Task.Factory.StartNew(async () =>
        {
            while (ws.IsConnected && !token.IsCancellationRequested)
            {
                String msg = await ws.ReadAsync();
                if (msg != null)
                    await ws.WriteAsync(ProcessResponse(msg));
            }
        },token);
    }
 }

创建新任务并不一定意味着新的线程,但这是正确的方法吗?我利用了ThreadPool,还有什么我可以做的吗?

这种方法有什么潜在的陷阱吗?

解决方法

等待任务在你的Main将不会编译;你必须使用task.Wait();如果你想阻止它.

此外,您应该在异步编程中使用Task.Run而不是Task.Factory.StartNew.

Creating new Task does not necessarily mean new thread,but is this the right way?

您当然可以启动单独的任务(使用Task.Run).虽然你不必.您可以轻松调用单独的异步方法来处理单个套接字连接.

但是,您的实际插座处理有一些问题. Connected属性几乎没用.你应该永远不断地从一个连接的套接字读取,即使你在写信给它.此外,您应该写“keepalive”消息或在您的读取超时,以便您可以检测半开状态.我维持一个TCP/IP .NET FAQ解释这些常见的问题.

我真的强烈建议人们不要写TCP / IP服务器或客户端.有大量的陷阱.如果可能,自主托管WebAPI和/或SignalR将会更好.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读