[COLOR="Blue"] Public Sub[/COLOR] SMPPWorkCycle([COLOR="Blue"]ByVal[/COLOR] data [COLOR="Blue"]As Object[/COLOR])
[COLOR="Blue"]Dim[/COLOR] netmod [COLOR="Blue"]As New[/COLOR] NetworkModule [COLOR="Green"]'Это узкозаточенная оболочка над классом System.Net.Sockets.Socket[/COLOR]
[COLOR="Blue"]Try[/COLOR]
[COLOR="Blue"]While [/COLOR](m_state = ServiceState.Started)
netmod.Connect(ipaddr, port)
[COLOR="Blue"]While [/COLOR]m_state = ServiceState.Started [COLOR="Blue"]And [/COLOR]netmod.Connected
DoSomething(netmod) [COLOR="Green"]'Тут мы в цикле обращаемся к БД и по сети шлём данные.[/COLOR]
[COLOR="Blue"]End While[/COLOR]
[COLOR="Blue"]If[/COLOR] netmod.Connected = False Then
[COLOR="Blue"]Try[/COLOR]
netmod.Disconnect()
[COLOR="Blue"]Catch[/COLOR] ex [COLOR="Blue"]As[/COLOR] Exception
[COLOR="Green"]'Обрабатываем исключение[/COLOR]
[COLOR="Blue"]End Try
End If
End While
Catch[/COLOR] ex [COLOR="Blue"]As[/COLOR] Exception
[COLOR="Green"]'Обрабатываем исключение[/COLOR]
[COLOR="Blue"]End Try
End Sub[/COLOR]
Любопытное поведение System.Net.Sockets
Имеется поток, в котором выполняется примерно такая функция:
Код:
Код:
m_state = ServiceState.Started
Амбула.
Гадость ситуации в том, что иногда процедура DoSomething не знает о том, что сокет отключился, поэтому подвешивает сервер обращениями к БД. В самой процедуре DoSomething имеется цикл по условию
Код:
[COLOR="Blue"]While [/COLOR](netmod.Connected = [COLOR="Blue"]True[/COLOR])
Отсюда вопросы:
- Насколько быстро свойство socket.Connected меняет своё состояние? Есть подозрение, что сразу, но тогда возникает второй вопрос:
- Почему при попытке послать данные в отключенный сокет не всегда возникает исключение с выходом из функции?
На собственном опыте сталкивался с такой проблемой. Свойство Connected порой выдает желаемое за действительное (подключения по сокету нет, а оно уверяет, что все в порядке), но в таком случае при посылке (Send), вываливается исключение (это собственно и означает, что с подключением беда). После этого "передергиваем" сокет (например, тупо создаем новый объект сокета) и все работа возобновляется.
Спасибо. :) Мы тоже это заметили. Единственное, что помогает, это отлов исключений, они, к счастью, возникают исправно.
- Свойство Connected обновляется в момент проведения последней операции на сокете. Это значит, что если мы успешно отправили данные, а удалённый хост в через какое-то время взял и отвалился, свойство Connected об этом ничего знать не будет, поэтому при попытке повторной отправки данных возникнет исключение. Это не баг, это фича от MS, причём, как ни парадоксально звучит, фича довольно логичная.
- Хочу предостеречь от одной своей ошибки: если отправка данных не удалась, не стоит вызывать метод сокета Disconnect(), поскольку в этом случае возникнет исключение (ельзя разорвать уже разорванное соединение), которое вы забудете обработать. В этом случае оно непременно повесит функцию более верхнего уровня.
- Проверить наличие связи в данный момент по значению свойства Connected невозможно, оно лишь показывает, что связь была во время последней операции, и предполагается, что она есть и сейчас, хотя на самом деле это не обязательно так. Отсюда вывод: надо всегда работать с сокетами в блоке Try...Catch, либо обрабатывать исключения в функции верхнего уровня.
- Из вышесказанного следует: проверьте, не потеряете ли вы данные при обработке исключения, предусмотрите механизм повторной отправки данных.
- Характерно, что при разрыве связи по нашей инициативе свойство Connected принимает значение False, а при разрыве по инициативе удалённого хоста оно не принимает нового значения, поэтому при отправке данных возникнет исключение, а при приёме по истечению таймаута сокет вернёт ноль байт, что тоже следует рассматривать как разрыв соединения и соответственно обрабатывать.