Отключаем TCPClient и видим это на другой стороне - PullRequest
2 голосов
/ 24 сентября 2010

Я пытаюсь отключить клиента от сервера, но сервер по-прежнему видит его подключенным.Я не могу найти решение этой проблемы, и выключение, отключение и закрытие не работают.

Некоторый код для моего отключения от клиента и проверки на сервере:

Клиент:

  private void btnDisconnect_Click(object sender, EventArgs e)
    {
        connTemp.Client.Shutdown(SocketShutdown.Both);
        connTemp.Client.Disconnect(false);
        connTemp.GetStream().Close();
        connTemp.Close();
    }

Сервер:

    while (client != null && client.Connected)
            {
                NetworkStream stream = client.GetStream();
                data = null;

                try
                {
                    if (stream.DataAvailable)
                    {
                        data = ReadStringFromClient(client, stream);
                        WriteToConsole("Received Command: " + data);
                    }
                } // So on and so on...

Естьбольше пишет и читает дальше в коде.

Надеюсь, что вы все можете помочь.

ОБНОВЛЕНИЕ: Я даже пытался передать TCP-клиент по ref, предполагая, что была проблема с областью действия и client.Connected остается верным даже после чтения.Что не так?

Второе обновление !!:

Вот решение проблемы.Посмотрите и, основываясь на этом, определите, подключены вы или нет.

  if (client.Client.Poll(0, SelectMode.SelectRead))
                    {
                        byte[] checkConn = new byte[1];
                        if (client.Client.Receive(checkConn, SocketFlags.Peek) == 0)
                        {
                            throw new IOException();
                        }
                    }

Ответы [ 4 ]

7 голосов
/ 24 сентября 2010

Вот решение !!

  if (client.Client.Poll(0, SelectMode.SelectRead))
                {
                    byte[] checkConn = new byte[1];
                    if (client.Client.Receive(checkConn, SocketFlags.Peek) == 0)
                    {
                        throw new IOException();
                    }
                }
1 голос
/ 24 сентября 2010

Я не уверен насчет класса NetworkStream, но я думаю, что он будет вести себя подобно классу Socket, так как он в основном является классом-оберткой. Обычно сервер не знает, что клиент отключен от сокета, если он не выполняет операцию ввода-вывода на сокете (чтение или запись). Однако, когда вы вызываете BeginRead для сокета, обратный вызов не вызывается до тех пор, пока не будут считаны данные из сокета, поэтому вызов EndRead и получение результата чтения байтов, возвращающего 0 (ноль), означает, что сокет был отключен. Если вы используете Read и получаете результат чтения с нулевым байтом, я подозреваю, что вы можете проверить свойство Connected в базовом классе Socket, и оно будет иметь значение false, если клиент отключился, поскольку в сокете была выполнена операция ввода-вывода.

1 голос
/ 24 сентября 2010

Из документации MSDN :

Свойство Connected получает состояние подключения клиентского сокета на момент последней операции ввода-вывода.

Когда возвращается false, клиентский сокет либо никогда не был подключен, либо больше не подключен.Поскольку свойство Connected отражает только состояние соединения на момент последней операции, вы должны попытаться отправить или получить сообщение, чтобы определить текущее состояние.После сбоя отправки сообщения это свойство больше не возвращает true.Обратите внимание, что это поведение предусмотрено дизайном.Вы не можете надежно проверить состояние соединения, потому что во время между проверкой и отправкой / получением соединение могло быть потеряно.Ваш код должен предполагать, что сокет подключен, и изящно обрабатывать неудачные передачи.

0 голосов
/ 24 сентября 2010

Это общая проблема TCP, см .:

Обходной путь для этого состоит в том, чтобы посылать объем данных, ожидаемый как часть протокола. Это то, что HTTP 1.1 делает с использованием заголовка Content-Length (для всей сущности) или с использованием кодировки передачи по частям (с различными размерами чанков).

Другим способом является регулярная отправка «NOOP» или аналогичных команд (по сути, сообщений, которые ничего не делают, но проверяют, что связь все еще открыта) как часть вашего протокола.

(Вы также можете добавить в свой протокол команду, которую клиент может отправить на сервер, чтобы корректно закрыть соединение, но не получая его, не будет означать, что клиент не отключился.)

...