TCP-сервер - не удается получить доступ к удаленному объекту

У меня есть рабочий TCP-сервер. Моя проблема в том, что когда я вызываю метод TCPListener Stop(), я получаю исключение (не могу получить доступ к удаленному объекту) на TCPClient. И я думаю, это имеет смысл, что он выдает исключение, потому что я закрыл Listner, чтобы он удалил все объекты, которые у него были. Но затем асинхронный метод AcceptTcpClientAsync() завершается, и возникает исключение. (это мое предположение, почему это происходит). Но я понятия не имею, как решить эту проблему.

Весь код доступен на https://github.com/xszaboj/tcpserver в ветке async2.

Исключение выдается в классе TcpServer.

public class TcpServer
{
    private bool _running = true;
    TcpListener _serverSocket;
    private ClientHandler _handler;


    public async void Start()
    {
        _running = true;
        _handler = new ClientHandler();
        _serverSocket = new TcpListener(GetIP(), 8889);
        _serverSocket.Start();
        while (_running)
        {
            try
            {
                TcpClient tcpClient = await _serverSocket.AcceptTcpClientAsync();
                Task t = Process(tcpClient);
                await t;
            }
            catch (Exception)
            {
                //Just suppress exception
            }
        }
    }

    private async Task Process(TcpClient tcpClient)
    {
        try
        {
            NetworkStream networkStream = tcpClient.GetStream();
            StreamReader reader = new StreamReader(networkStream);
            while (true)
            {
                string request = await reader.ReadLineAsync();
                if (request != null)
                {
                    _handler.ExecuteCommand(request);
                }
                else
                    break; // client closede connection
            }
            tcpClient.Close();
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
            if (tcpClient.Connected)
                tcpClient.Close();
        }
    }

    public void Stop()
    {
        _running = false;
        _serverSocket.Stop();
    }

    private IPAddress GetIP()
    {
        string hostName = Dns.GetHostName();
        IPHostEntry ipHostInfo = Dns.GetHostEntry(hostName);
        foreach (IPAddress address in ipHostInfo.AddressList)
        {
            if (address.AddressFamily == AddressFamily.InterNetwork)
            {
                return address;
            }
        }
        return null;
    }
}

Как раз там, где написано //Просто подавить исключение Это исключение возникает после вызова метода Stop().

Спасибо за любые предложения по улучшению этого решения.


person xszaboj    schedule 09.11.2016    source источник
comment
Сервер никогда не должен закрывать соединение. Соединение всегда должно открываться и закрываться от клиента. Сервер является подчиненным для клиента. Если сервер закроет соединение с клиентом, который все еще отправляет данные, это вызовет исключения.   -  person jdweng    schedule 09.11.2016
comment
Итак, вы говорите, что мое решение для подавления исключений - лучшее, что я могу получить?   -  person xszaboj    schedule 09.11.2016
comment
Когда я пытаюсь воспроизвести проблему, исключение выдается из TcpListener.EndAcceptTcpClient (что имеет смысл), а не из экземпляра TcpClient.   -  person C.Evenhuis    schedule 09.11.2016
comment
Также см. stackoverflow. ком/вопросы/19220957/   -  person C.Evenhuis    schedule 09.11.2016
comment
Большое спасибо C.Evenhuis   -  person xszaboj    schedule 09.11.2016