无限while循环仅获得一个结果

时间:2020-01-10 23:13:58

标签: c# multithreading tcp

我正在编写一个P2P程序,该程序必须在多个实例之间发送和接收数据。 当我创建单独的线程来侦听infinity while循环中的传入数据时,我遇到了一个问题,但是我只收到第一条消息,然后什么也没有。 我究竟做错了什么? 代码:

Task t = new Task(() => {
                try {
                    server = new TcpListener(IPAddress.Parse(STD_IP), STD_PORT);
                    server.Start();
                    odjemalec = server.AcceptTcpClient();
                    nwStream = odjemalec.GetStream();
                }
                catch (Exception ex) {
                    Console.WriteLine("Error\n" + ex.Message + "\n" + ex.StackTrace);
                }
                while(true) {
                    listen();
                }


            });
            t.Start();

2 个答案:

答案 0 :(得分:0)

如果要使用任务(我强烈建议使用这种方法),则每个传入连接都需要监听器任务 TcpClient Responder任务

这是基本的TCP侦听器任务

static async Task StartTcpServerAsync()
{
    var tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, 9999));
    tcpListener.Start();
    while (true)
    {
        var tcpClient = await tcpListener.AcceptTcpClientAsync();
        _ = StartTcpClientAsync(tcpClient);
    }
}

我们启动TcpListener并开始监听连接。每次建立连接时,我们都会将关联的TcpClient交给新的Task。

这是服务器端TCP客户端任务-它位于服务器上,由侦听器启动

static async Task StartTcpClientAsync(TcpClient tcpClient)
{
    Console.WriteLine($"Connection from: [{tcpClient.Client.RemoteEndPoint}]");

    var stream = tcpClient.GetStream();
    var buffer = new byte[1024];

    while (true)
    {
        int x = await stream.ReadAsync(buffer, 0, 1024);
        Console.WriteLine($"[{tcpClient.Client.RemoteEndPoint}] _ " +
            $"read {x} bytes {System.Text.Encoding.UTF8.GetString(buffer)}");
    }
}

在此示例中,我们只写出接收到的字节。

最后

为了完整起见,这里有一个Main也是一个TCPSender-通常,Sender将位于完全不同的计算机上,但是为了展示Tasks的强大功能,我们将在同一过程中运行它。

static async Task Main(string[] args)
{
    _ = StartTcpServerAsync();
    await Task.Delay(2000);
    await RunSenderAsync();
}
static async Task RunSenderAsync()
{
    var tcpClient = new TcpClient("127.0.0.1", 9999);
    var s = tcpClient.GetStream();
    tcpClient.NoDelay = true;
    for (var i = 65; i < 91; i++)
    {
        s.Write(BitConverter.GetBytes(i), 0, 1);
        await Task.Delay(1000);
    }
}

我发现很多人感到困惑的地方是,对于每个收到的连接,服务器上都需要一个TcpClient。

答案 1 :(得分:0)

这个答案是给塞尔文的。

我将Main更改为运行三个RunSenderAsync客户端。

这是控制台窗口中的输出。如您所见,三个客户端连接到侦听器,该侦听器随后启动三个任务,每个任务将在WorkerThread池的Worker线程上运行。我已经更新了Writeline()以打印线程ID,以便您可以看到任务在WorkerThreads周围移动。

BiDi source: [127.0.0.1:50279] connected to Pipeline Server
Connection from: [127.0.0.1:50279]
BiDi source: [127.0.0.1:50280] connected to Pipeline Server
BiDi source: [127.0.0.1:50281] connected to Pipeline Server
Connection from: [127.0.0.1:50280]
[127.0.0.1:50280] read 1 bytes A                                                                                             
    ^^ On Thread ID: 7
[127.0.0.1:50279] read 1 bytes A                                                                                             
    ^^ On Thread ID: 6
Connection from: [127.0.0.1:50281]
[127.0.0.1:50281] read 1 bytes A                                                                                             
    ^^ On Thread ID: 5
[127.0.0.1:50280] read 1 bytes B                                                                                             
    ^^ On Thread ID: 7
[127.0.0.1:50279] read 1 bytes B                                                                                             
    ^^ On Thread ID: 8
[127.0.0.1:50281] read 1 bytes B                                                                                             
    ^^ On Thread ID: 5
[127.0.0.1:50279] read 1 bytes C                                                                                             
    ^^ On Thread ID: 6
[127.0.0.1:50281] read 1 bytes C                                                                                             
    ^^ On Thread ID: 5
[127.0.0.1:50280] read 1 bytes C                                                                                             
    ^^ On Thread ID: 7
[127.0.0.1:50280] read 1 bytes D                                                                                             
    ^^ On Thread ID: 5
[127.0.0.1:50279] read 1 bytes D                                                                                             
    ^^ On Thread ID: 7
[127.0.0.1:50281] read 1 bytes D                                                                                             
    ^^ On Thread ID: 8
[127.0.0.1:50280] read 1 bytes E                                                                                             
    ^^ On Thread ID: 5
[127.0.0.1:50281] read 1 bytes E                                                                                             
    ^^ On Thread ID: 7
[127.0.0.1:50279] read 1 bytes E                                                                                             
    ^^ On Thread ID: 8
[127.0.0.1:50280] read 0 bytes E  

这是完整的源代码:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;

namespace ReadAsync
{
    class Program
    {
        static async Task StartTcpClientAsync(TcpClient tcpClient)
        {
            Console.WriteLine($"    Connection from: [{tcpClient.Client.RemoteEndPoint}]");

            var stream = tcpClient.GetStream();
            var buffer = new byte[1024];

            while (true)
            {
                int x = await stream.ReadAsync(buffer, 0, 1024);
                Console.WriteLine($"    [{tcpClient.Client.RemoteEndPoint}] " +
                    $"read {x} bytes {System.Text.Encoding.UTF8.GetString(buffer)} "+
                    $"        ^^ On Thread ID: {Thread.CurrentThread.ManagedThreadId}");
            }
        }
        static async Task StartTcpServerAsync()
        {
            var tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, 9999));
            tcpListener.Start();

            while (true)
            {
                var tcpClient = await tcpListener.AcceptTcpClientAsync();

                _ = StartTcpClientAsync(tcpClient);
            }
        }
        static async Task Main(string[] args)
        {
            _ = StartTcpServerAsync();

            await Task.Delay(2000);

            _ = RunSenderAsync();
            _ = RunSenderAsync();
            await RunSenderAsync();
        }
        static async Task RunSenderAsync()
        {
            using var tcpClient = new TcpClient("127.0.0.1", 9999);

            Console.WriteLine($"    BiDi source: [{tcpClient.Client.LocalEndPoint}] connected to Pipeline Server");

            using var s = tcpClient.GetStream();

            tcpClient.NoDelay = true;

            for (var i = 65; i < 70; i++)
            {
                s.Write(BitConverter.GetBytes(i), 0, 1);
               await Task.Delay(1000);
            }
        }
    }
}