Отключение TcpClient во время асинхронного чтения - PullRequest
3 голосов
/ 23 июня 2011

У меня есть несколько вопросов о завершении tcp-соединения.

  1. Клиент подключается к моему серверу с помощью Tcp, после принятия клиента с listener.BeginAcceptTcpClient(ConnectionEstabilishedCallback, null); я начинаю читать с networkStream.BeginRead(....).
    Что происходит, когда клиент отключается, пока я жду сообщения?(например, он теряет питание, интернет и т. д.)
    Как узнать, когда это произойдет?

  2. Если после успешного чтения я что-то сделаю,а затем позвоните networkStream.Close(); client.Close(); Что увидит клиент?Как завершить соединение «изящно»?

  3. Что произойдет, если я жду чтения (с BeginRead), а затем (в другом потоке) закрываю тот же поток?

РЕДАКТИРОВАТЬ В ДОБАВИТЬ: У меня есть сообщение для пинг-понга между клиентом и сервером.Этого достаточно?Если я не получаю пинг, прекратить мой NetworkStream?конечно, должно быть что-то лучше.

Ответы [ 3 ]

2 голосов
/ 23 июня 2011

1- Если клиент отключился из-за отсоединения кабеля, вы не узнаете об этом до следующего чтения или записи в сокет. также обратите внимание, что значение свойства tcpClient.Connected не является надежным, оно зависит от последнего сообщения; поэтому, если последнее сообщение было успешным, тогда его значение равно true, иначе оно равно false. для получения дополнительной информации об этом чеке это .

2- Если вы закрываете сетевой поток и клиент, это изящное завершение клиента.

3- Я не знаю, проведите тест.

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

Используйте это свойство IsConnected, чтобы проверить, подключен ли tcpClient:

public static bool IsConnected
{
    get
    {
        try
        {
            //return _tcpClient != null && _tcpClient.Client != null && _tcpClient.Client.Connected;

            if (_tcpClient != null && _tcpClient.Client != null && _tcpClient.Client.Connected)
            {

                /* As the documentation:
                    * When passing SelectMode.SelectRead as a parameter to the Poll method it will return 
                    * -either- true if Socket.Listen(Int32) has been called and a connection is pending;
                    * -or- true if data is available for reading; 
                    * -or- true if the connection has been closed, reset, or terminated; 
                    * otherwise, returns false
                    */

                // Detect if client disconnected
                if (_tcpClient.Client.Poll(0, SelectMode.SelectRead))
                {
                    byte[] buff = new byte[1];
                    if (_tcpClient.Client.Receive(buff, SocketFlags.Peek) == 0)
                    {
                        // Client disconnected
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }

                return true;
            }
            else
            {
                return false;
            }
        }
        catch
        {
            return false;
        }
    }
}
2 голосов
/ 23 июня 2011

Что происходит, когда клиент отключается, пока я жду сообщения? (например, он теряет питание, интернет и т. д.) Как я узнаю, когда это произойдет?

По разным причинам отключения происходят разные вещи.

Изящное отключение обнаружено, когда вы получаете 0 байтов от socket.EndRead. Другие отключения приведут к SocketException для EndRead или Send

Если после успешного чтения я что-то делаю, а затем вызываю networkStream.Close (); client.Close (); Что увидит клиент? Как прекратить соединение "изящно"?

Закрыть сделает это изящно.

Что произойдет, если я жду чтения (с BeginRead), а затем (в другом потоке) закрою тот же поток?

Вы получите исключение. Либо ObjectDisposedException (если вы распоряжаетесь клиентом), либо IOException

0 голосов
/ 23 июня 2011
public class Example
{
    static NetworkStream stream;
    static TcpClient client;

    public static void Main(String[] args)

        String message = String.Empty;

        //TCP connection
 Recon: Console.WriteLine("Connecting...");
        Int32 port = 3333;
        try
        {
            client = new TcpClient("ip.ip.ip.ip", port); //Try to connect
        }
        catch
        {
            Console.WriteLine("Problem while connecting!");
            Thread.Sleep(10000); //Waiting 10s before reconnect
            goto Recon;
        }

        Console.WriteLine("Connection established!\n");

        stream = client.GetStream();

        while (true)
        {

            //Buffer
            byte[] received_bytes = new Byte[1024];
            message = "";

            Console.WriteLine("Waiting to receive message...\n");

            Int32 bytes = stream.Read(received_bytes, 0, received_bytes.Length);
            message = System.Text.Encoding.GetEncoding("iso-8859-1").GetString(received_bytes, 0, bytes);

            if (bytes == 0) //If connection abort while reading
            {
                Console.WriteLine("Connection failed!");

                //Recconecting
                goto Recon;
            }

            Console.WriteLine("Received message: " + message);
        }
    }
}
...