Блокировка сокета C# с нулевыми данными

Я реализовал клиент C# tcp-ip (как для синхронного, так и для асинхронного чтения). После каждого SocketException я автоматически переподключаю соединение с сервером.

Затем я проверил связь клиента с ncat в windows. Здесь, если я убью ncat, он выдаст исключение SocketException в клиенте C#, и все будет работать так, как я себе представляю.

Но потом я проверил это с помощью ncat в linux - здесь связь работает нормально, но если я убью ncat server (те же настройки, что и в Windows - ncat -l -k -p xxxx), огромное количество пустых данных (ноль B) полученный в обратном вызове (или ожидании на сокете в версии синхронизации), и никакое исключение не выдается.

Одна вещь состоит в том, что версия ncat для Windows / Unix может иметь другое поведение. Но все же мне нужно решить это странное поведение для любой версии сервера tcp-ip.

    /* ------------------------------------------------------------------------- */
    public void WaitForData()
    {
        try
        {
            if (callback == null)
                callback = new AsyncCallback(OnDataReceived);

            SocketPacket packet = new SocketPacket();
            packet.thisSocket = socket;

            m_result = socket.BeginReceive
                (packet.dataBuffer, 0, 256,
                SocketFlags.None, callback, packet);
        }
        catch (SocketException ex) { ///reconnecting }
    }

    /* ------------------------------------------------------------------------- */
    public class SocketPacket
    {
        public System.Net.Sockets.Socket thisSocket;
        public byte[] dataBuffer = new byte[256];
    }

    /* ------------------------------------------------------------------------- */
    public void OnDataReceived(IAsyncResult asyn)
    {
        try
        {
            SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
            int iRx = theSockId.thisSocket.EndReceive(asyn);
            char[] chars = new char[iRx];
            System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
            int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
            string szData = new string(chars);
            szData = szData.Replace("\n", String.Empty);

            processMessage(szData);

            WaitForData();
        }

        catch (ObjectDisposedException) { }
        catch (SocketException ex) { ///reconnecting }
    }

Спасибо!

2 ответа

Решение

решаемая

В обратном вызове OnDataReceived я проверяю количество входящих данных, поэтому я делаю:

if (iRx == 0)
   throw new SocketException(Convert.ToInt16(SocketError.HostDown));

TCP-получатель никогда не сможет получить точный статус удаленного соединения. Завершение процесса отправит FIN (получение равно нулю) или RST(исключение получения) в зависимости от реализации стека TCP/IP. Существуют и другие условия, когда приложение полностью не знает об обрыве соединения. Предположим, что если удаленная система принудительно перезагружена или провод кабеля отключен или IP-адрес изменен, вы не сможете узнать, что соединение разорвано, пока не отправите некоторые данные. Если вашему приложению нужно знать состояние соединения, оно может отправлять некоторые фиктивные данные каждую минуту, чтобы убедиться, что соединение активно.

Другие вопросы по тегам