C#异步TCP侦听器不取消循环

时间:2017-12-29 12:54:12

标签: c# asynchronous tcplistener

我正在使用TCPListener类异步编写C#中的服务器。我目前有以下代码作为我的网络监听器类:

public class NetworkListener
{
    private readonly SessionController _sessions;
    private readonly TcpListener _server;

    public NetworkListener(KernelConfiguration configuration, SessionController sessions)
    {
        _server = new TcpListener(new IPEndPoint(IPAddress.Any, configuration.Network.port));
        _server.Start();

        _sessions = sessions;
    }

    public async Task StartAccepting(CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            var client = await _server.AcceptTcpClientAsync();
            Console.WriteLine($"New connection from {client.Client.RemoteEndPoint}.");
            _sessions.AddSession(client, Guid.NewGuid(), out var session);
            await session.StartReceiving();
        }

        Console.WriteLine("stop");
    }

    public void Dispose()
    {
        _server.Stop();
    }
}

作为我的program.cs,我有:

internal class Program
{
    private static NetworkListener _networkListener;
    private static CancellationTokenSource _cancellationTokenSource;

    private static async Task Main(string[] args)
    {
        _networkListener = new NetworkListener(new KernelConfiguration(), new SessionController());
        _cancellationTokenSource = new CancellationTokenSource();

        var thread = new Thread(ProgressConsoleCommands);
        thread.Start();

        try
        {
            await _networkListener.StartAccepting(_cancellationTokenSource.Token);
        }
        finally
        {
            _networkListener.Dispose();
        }
    }

    private static void ProgressConsoleCommands()
    {
        while (true)
        {
            var command = Console.ReadLine();
            Console.WriteLine(command);

            switch (command)
            {
                case "close":
                    Console.WriteLine("called");
                    _cancellationTokenSource.Cancel();
                    break;
            }
        }
    }
}

目前发生的事情:

我启动了我的程序。它启动TcpListener。我可以连接到TcpListener正在侦听的端口。当我输入“close”(当然没有引号)时,它会写入“called”。但是,“stop”不会写入控制台,TcpListener仍然接受新问题。

期望状态:

每当我输入“close”时,它应该停止接受新连接,写入“stop”并退出循环。然后它应该调用我的NetworkListener类的Dispose函数来完全停止TcpListener并处理它。

1 个答案:

答案 0 :(得分:0)

在调用AcceptTcpClientAsync()之前,您可以先尝试在while循环中检查TcpListener.Pending(),这样循环只会阻止实际存在要处理的新连接。

https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.pending(v=vs.110).aspx

编辑(0):如果你这样做,你可能想在while循环中添加Thread.Sleep,以最小化CPU负载

编辑(1):所以我的目标是这样的:

$("#input2").val($("#input1").value.toLocaleLowerCase().replace(/\s/g, ''));

正如您所描述的那样,问题似乎是"等待AcceptTcpClientAsync()"无限期地阻塞while循环,直到新客户端尝试连接到服务器。

正如@Damien_The_Unbeliever在他的评论中指出的那样,你可以通过简单地为TcpListener提供一个新的客户端连接来解锁它(以一种肮脏的方式)。

然而,上面的例子 - 实际上 - 一旦Thread.Sleep到期就执行取消