Каков наилучший способ сохранить проверку сокетов в .NET? - PullRequest
11 голосов
/ 04 октября 2008

Я ищу способ проверить работоспособность в .NET. Сценарий предназначен как для UDP, так и для TCP.

В настоящее время в TCP я подключаюсь к одной стороне, и, когда нет данных для отправки, она отправляет подтверждение активности каждые X секунд.

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

Один из способов, которыми я пытался сделать, - это блокировать прием и установить для RecieveTimeout сокета значение X секунд. Но проблема заключалась в том, что всякий раз, когда происходил тайм-аут, приемник сокета генерировал исключение SocketExeception, и сокет на этой стороне закрывался, это правильное поведение? почему сокет закрывается / умирает после тайм-аута, а не просто продолжается?

Проверка наличия данных и спящего режима неприемлема (поскольку я могу отстать при получении данных во время сна).

Итак, как лучше всего это сделать, и почему метод, который я описал с другой стороны, не работает?

Ответы [ 3 ]

17 голосов
/ 05 октября 2008

Если вы буквально имеете в виду «KeepAlive», попробуйте следующее.

    public static void SetTcpKeepAlive(Socket socket, uint keepaliveTime, uint keepaliveInterval)
    {
        /* the native structure
        struct tcp_keepalive {
        ULONG onoff;
        ULONG keepalivetime;
        ULONG keepaliveinterval;
        };
        */

        // marshal the equivalent of the native structure into a byte array
        uint dummy = 0;
        byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
        BitConverter.GetBytes((uint)(keepaliveTime)).CopyTo(inOptionValues, 0);
        BitConverter.GetBytes((uint)keepaliveTime).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
        BitConverter.GetBytes((uint)keepaliveInterval).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);

        // write SIO_VALS to Socket IOControl
        socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
    }
1 голос
/ 04 октября 2008

Согласно MSDN, исключение SocketException, генерируемое при превышении ReceiveTimeout в вызове приема , не будет закрывать сокет. В вашем коде происходит что-то еще.

Проверьте пойманные детали SocketException - возможно, это не тайм-аут в конце концов. Может быть, другая сторона соединения закрывает розетку.

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

0 голосов
/ 04 октября 2008

Поскольку вы не можете использовать блокирующий (синхронный) прием, вам придется согласиться на асинхронную обработку. К счастью, это очень легко сделать с .NET. Ищите описание BeginReceive () и EndReceive (). Или посмотрите эту статью или эту .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...