首页 文章

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

提问于
浏览
0

我正在使用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;
            }
        }
    }
}

What currently happens:

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

Desired state:

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

1 回答

  • 0

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

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

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

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

    while (!token.IsCancellationRequested) {
        if (_server.Pending()) {
            var client = await _server.AcceptTcpClientAsync();
            // insert code for handling new connection
        }
        Thread.Sleep(500);
    }
    

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

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

    但是,上面的例子应该 - 实际上 - 一旦Thread.Sleep到期就执行取消

相关问题