Как сказать, когда Сокет был разъединен

На стороне клиента я должен знать, когда/если мое сокетное соединение было повреждено. Однако Сокет. Связанное свойство всегда возвращает true, даже после того, как сторона сервера была разъединена, и я попытался отправить данные через него. Может любой помогать мне выяснить то, что продолжается здесь. Я должен знать, когда сокет был разъединен.

        Socket serverSocket = null;
        TcpListener listener = new TcpListener(1530);
        listener.Start();
        listener.BeginAcceptSocket(new AsyncCallback(delegate(IAsyncResult result)
        {
            Debug.WriteLine("ACCEPTING SOCKET CONNECTION");
            TcpListener currentListener = (TcpListener)result.AsyncState;
            serverSocket = currentListener.EndAcceptSocket(result);
        }), listener);


        Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, and it is
        clientSocket.Connect("localhost", 1530);
        Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be TRUE, and it is

        Thread.Sleep(1000);
        serverSocket.Close();//closing the server socket here
        Thread.Sleep(1000);

        clientSocket.Send(new byte[0]);//sending data should cause the socket to update its Connected property.
        Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, but its always TRUE
16
задан BowserKingKoopa 31 March 2010 в 18:49
поделиться

5 ответов

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

Если вам нечего писать... тогда какая разница, что сокет отключен? Он может быть отключен сейчас, но вернуться до того, как он вам понадобится - зачем разрывать его, а затем зацикливать повторное подключение, пока связь не будет восстановлена... особенно если вам все равно нечего сказать?

Если вас это беспокоит, реализуйте в своем протоколе функцию keep alive. Тогда вам будет что сказать каждые 30 секунд или около того.

4
ответ дан 30 November 2019 в 22:24
поделиться

После некоторого тестирования выяснилось, что документация для Socket.Connected неверна или, по крайней мере, вводит в заблуждение. clientSocket.Connected станет ложным только после вызова clientSocket.close () . Я думаю, что это возврат к исходному API сокетов C Berkeley и его терминологии. Сокет привязывается, когда с ним связан локальный адрес, и сокет подключается, когда с ним связан удаленный адрес. Несмотря на то, что удаленная сторона закрыла соединение, локальный сокет все еще имеет ассоциацию, и поэтому он все еще «подключен».

Однако вот метод, который действительно работает:

!(socket.Poll(0, SelectMode.SelectRead) && socket.Available == 0)

Он основан на том факте, что закрытое соединение будет помечено как доступное для чтения, даже если данные недоступны.

Если вы хотите обнаружить такие условия, как обрыв сетевых кабелей или внезапное отключение компьютеров, ситуация немного сложнее. В этих условиях ваш компьютер никогда не получает пакет, указывающий, что сокет закрыт. Ему необходимо определить, что удаленная сторона исчезла, отправив пакеты и заметив, что ответ не возвращается.Вы можете сделать это на уровне приложения как часть своего протокола или использовать опцию TCP KeepAlive. Использовать TCP Keep Alive из .NET не так просто; вам, вероятно, лучше встроить механизм проверки активности в свой протокол (в качестве альтернативы, вы можете задать отдельный вопрос: «Как включить TCP Keep Alive в .NET и установить интервал проверки активности?»).

10
ответ дан 30 November 2019 в 22:24
поделиться

Может быть, решение состоит в том, чтобы отправить через него фиктивные данные и проверить, не истекло ли время ожидания?

3
ответ дан 30 November 2019 в 22:24
поделиться

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

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

В качестве решения я рекомендую не писать собственный ввод-вывод сокета и использовать чужое промежуточное ПО. Есть много хороших кандидатов. Не забудьте также рассмотреть простые службы очередей.

PS. Я бы предоставил URL-адреса для всего вышеперечисленного, но моя репутация (1) не позволяет этого.

2
ответ дан 30 November 2019 в 22:24
поделиться

ожидает ли метод clientSocket.Send (), пока пакет не будет подтвержден / заблокирован?

Если нет, ваш код переходит на следующую строку, в то время как сокет все еще пытается выяснить, что происходит.

0
ответ дан 30 November 2019 в 22:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: