C # WinForms (TcpClient) - невозможно прочитать / записать данные из / в транспортное соединение: существующее соединение было принудительно закрыто удаленным хостом - PullRequest
1 голос
/ 09 марта 2012

Я понимаю, что есть много статей на эту тему, но я пытаюсь найти объяснение этой конкретной проблемы.

Сервер является сервером АТС Asterisk, который постоянно записывает данные вызовов в сокет.

В настоящее время к серверу подключается около 10 клиентов, которые случайным образом получают исключение при чтении / записи в транспортное соединение. Это может быть при первом чтении / записи при загрузке программы или через 4 часа. Для этой проблемы нет последовательности или закономерности. Клиенты не получают все это одновременно, но в разное время.

У кого-нибудь есть идея, почему это может происходить? Кроме того, поскольку я новичок в сетевом программировании, какой будет лучший и самый изящный способ переподключения tcp-клиента к серверу при обнаружении этого исключения?

Заранее спасибо.

    private TcpClient client;
    private NetworkStream stream;
    private Encoding encoding;

    private void frmMain_Load(object sender, EventArgs e)
    {   
        this.client = new TcpClient("192.168.0.100", 5038);
        this.stream = this.client.GetStream();
        this.encoding = Encoding.ASCII;

        if (client.Connected)
            BeginRead();
    }

    private void BeginRead()
    {
        try
        {
            NetworkStream stream = this.client.GetStream();
            byte[] buffer = new byte[client.ReceiveBufferSize];
            IAsyncResult ar = stream.BeginRead(buffer, 0, buffer.Length, OnReadComplete, buffer);
        }
        catch (IOException ioex)
        {
            //Unable to read data from the transport connection caught here.
            //How to reconnect gracefully?
        }
        catch (Exception ex)
        {
            //Handle...
        }
    }

    private void OnReadComplete(IAsyncResult ar)
    {
        try
        {
            NetworkStream stream = this.client.GetStream();
            byte[] buffer = (byte[])ar.AsyncState;
            int bytesRead = stream.EndRead(ar);

            if (bytesRead > 0)
            {
                //Process response here...
            }

            BeginRead();  //Read again after read completed
        }
        catch (Exception ex)
        {
            //Handle...
        }
    }

    private void BeginWrite(string msg)
    {
        try
        {
            byte[] data = encoding.GetBytes(msg);
            IAsyncResult ar = stream.BeginWrite(data, 0, data.Length, this.OnWriteComplete, stream);
            stream.Flush();
        }
        catch (IOException ioex)
        {
            //Unable to write data to the transport connection caught here.
            //How to reconnect gracefully?
        }
        catch (Exception ex)
        {
            //Handle...
        }
    }

    private void OnWriteComplete(IAsyncResult ar)
    {
        try
        {
            NetworkStream arStream = (NetworkStream)ar.AsyncState;
            arStream.EndWrite(ar);
        }
        catch (Exception ex)
        {
            //Handle...
        }
    }

1 Ответ

0 голосов
/ 09 марта 2012

Я подозреваю, что это потому, что вы забыли «закрыть» объекты «NetworkStream».Если вы этого не сделаете, GC будет.Однако когда GC собирает объекты 'NetworkStream', это не является детерминированным, поэтому вы видите это случайное поведение.

...