首页 > 解决方案 > 无限while循环只得到一个结果

问题描述

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

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();

标签: c#multithreadingtcp

解决方案


如果您想使用任务(我强烈推荐这种方法),您需要为每个传入连接创建一个侦听器任务和一个TcpClient 响应程序任务。

这是一个基本的 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交给一个新任务。

这是一个服务器端 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。


推荐阅读