При инициализации клиентского приложения, использующего Remoting, в условиях диагностированной поломки в сети (выдернут кабель из карты и горит соответствующий значок или сетевое соединение вообще отключено через Control Panel\Network and Dial-up Connection), после восстановления сетевого соединения вызовы к серверным методам проходят нормально, но при попытке сервера обратится к клиентскому интерфейсу обратной связи выскакивает ошибка: «No connection could be made because target machine actively refuse it». Причем в случае если поломка не диагностирована явно (серверное приложение не запущено или нет доступа к серверной машине, но сама сеть есть), все работает нормально – после восстановления связи вызовы и от клиента к серверу, и от сервера к клиенту идут нормально.
Пробовал повторно инициализировать Remoting – сначала удалял все каналы, а потом снова создавал в новых условиях, но это не помогает и приходится все равно перезапускать клиентское приложение целиком.
Буду очень признателен, за идеи – как заставить Remoting заново инициализироваться без перезапуска приложения, или каким-либо другим способом решить вышеописанную проблему.
Здравствуйте, arhangel, Вы писали:
A>При инициализации клиентского приложения, использующего Remoting, в условиях диагностированной поломки в сети (выдернут кабель из карты и горит соответствующий значок или сетевое соединение вообще отключено через Control Panel\Network and Dial-up Connection), после восстановления сетевого соединения вызовы к серверным методам проходят нормально, но при попытке сервера обратится к клиентскому интерфейсу обратной связи выскакивает ошибка: «No connection could be made because target machine actively refuse it».
А что показывает netstat — порт на клиенте открыт?
Как зарегистрированы объекты на сервере? Небось Singleton или Singlecall? Если да, то серверные методы и будут вызываться восстановления линка.
Как сервер знает о клиенте? Небось передали ссылку на клиентский объект? Если да, то не будет работать коллбэк, пока снова не получите на сервере валидную ссылку на клиентский объект.
Re[2]: .NET Remoting
От:
Аноним
Дата:
04.10.05 09:35
Оценка:
Здравствуйте, oleksab, Вы писали:
O>А что показывает netstat — порт на клиенте открыт?
netstat, естественно показывает, что порт закрыт. Но как сделать так, чтобы он был открытый?
Re[2]: .NET Remoting
От:
Аноним
Дата:
04.10.05 09:43
Оценка:
Здравствуйте, hugo, Вы писали:
H>Здравствуйте, arhangel, Вы писали:
H>Как зарегистрированы объекты на сервере? Небось Singleton или Singlecall? Если да, то серверные методы и будут вызываться восстановления линка.
Серверный объект зарегистрирован как Singleton, причем метод InitializeLiftimeService переопределен, т.е. это синглетон с неограниченным временем жизни. Клиентские объекты не зарегистрированны никак — они реализуются определенный интерфейс и наследуются от MarshalByRefObject. Метод серверного объекта принимает в качестве параметра ссылку на реализацию интерфейса и дергает его методы. При этом автоматическая десериализация на сервере включена и при нормальной сети все работает как часы.
H>Как сервер знает о клиенте? Небось передали ссылку на клиентский объект? Если да, то не будет работать коллбэк, пока снова не получите на сервере валидную ссылку на клиентский объект.
Ссылка передается свеженькая на новый объект по новому каналу, другое дело, что серверная часть клиентского канала не принимает соединение при попытке обратится к объекту с сервера.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, hugo, Вы писали:
H>>Здравствуйте, arhangel, Вы писали:
H>>Как зарегистрированы объекты на сервере? Небось Singleton или Singlecall? Если да, то серверные методы и будут вызываться восстановления линка.
А>Серверный объект зарегистрирован как Singleton, причем метод InitializeLiftimeService переопределен, т.е. это синглетон с неограниченным временем жизни. Клиентские объекты не зарегистрированны никак — они реализуются определенный интерфейс и наследуются от MarshalByRefObject. Метод серверного объекта принимает в качестве параметра ссылку на реализацию интерфейса и дергает его методы. При этом автоматическая десериализация на сервере включена и при нормальной сети все работает как часы.
H>>Как сервер знает о клиенте? Небось передали ссылку на клиентский объект? Если да, то не будет работать коллбэк, пока снова не получите на сервере валидную ссылку на клиентский объект.
А>Ссылка передается свеженькая на новый объект по новому каналу, другое дело, что серверная часть клиентского канала не принимает соединение при попытке обратится к объекту с сервера.
Ну, вот, разницу ты и сам подтвердил А теперь попробуй чисто в виде экскримента зарегистрить на клиенте объект как Singleton или Singlecall и обратись к нему также, как к серверному объекту: после восстановление линка будет все работать.
Можно еще как и раньше передавать его (клиентский MBR) на сервер, но время жизни вечное сделать. Тоже все должно быть ок после восстановления связи.
Более того, если для клиентского MBR'а не переопределен Lifetime (или нет спонсора), то он даже без обрыва линка может умереть после некоторого бездействия.
Re[2]: .NET Remoting
От:
Аноним
Дата:
04.10.05 11:45
Оценка:
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, arhangel, Вы писали:
GZ>stack trace показать можешь?
GZ>С уважением, Gleb. GZ>ЗЫ у меня такое было, но из-за обрыва коннекта с БД.
Сори за тормоза — у нас инет отваливался...
Вот так выгляди стэк вызовов (лучше смотреть снизу вверх):
А вот тут и происходит облом — не удается соединится с клиентским приложением так как у него битый канал...
Это тот самый метод, который дернул клиент (ссылка на интерфейс обратной связи
представлена в виде TransparentProxy, но это все прозрачно и для клиента,
и для сервера)
Здравствуйте, hugo, Вы писали:
H>>>Как сервер знает о клиенте? Небось передали ссылку на клиентский объект? Если да, то не будет работать коллбэк, пока снова не получите на сервере валидную ссылку на клиентский объект.
А>>Ссылка передается свеженькая на новый объект по новому каналу, другое дело, что серверная часть клиентского канала не принимает соединение при попытке обратится к объекту с сервера.
H>Ну, вот, разницу ты и сам подтвердил А теперь попробуй чисто в виде экскримента зарегистрить на клиенте объект как Singleton или Singlecall и обратись к нему также, как к серверному объекту: после восстановление линка будет все работать.
К сожалению, так не получится – сервер должен работать не с каким-либо объектом, а с конкретным объектом. В данном случае именно с тем, ссылку на который передал клиент. На самом деле, если инициализировать сервер в «плохих» условиях, то с ним будет происходить та же ошибка – после восстановления сети клиенты сервер не видят. При этом если сервер был инициализирован при нормальной сети, а потом произошел разрыв, после восстановления сетки клиенты соединяются с ним нормально. Просто для сервера эта ситуация не критична.
H>Можно еще как и раньше передавать его (клиентский MBR) на сервер, но время жизни вечное сделать. Тоже все должно быть ок после восстановления связи.
Дело в том, что объект для обратной связи на клиенте создается уже после того, как связь восстановиться. До этого у сервера не было никаких ссылок на него, и у клиента тоже. Т.е. время жизни здесь не поможет.
H>Более того, если для клиентского MBR'а не переопределен Lifetime (или нет спонсора), то он даже без обрыва линка может умереть после некоторого бездействия.
Даже если на него как на локальный объект остались ссылки у других клиентских объектов? А если этот метод для него переопределить, будет ли GC его собирать, когда на него не останется локальных ссылок?
Пока удалось решить проблему следующим образом – перед созданием канала Remoting идет попытка соединения с указанным в URI сервером с помощью простого TcpClient. Если попытка успешна, то канал открывается и все работает. Т.е. получается так, что при отсутствии сети канал не будет инициализироваться.
Однако такой вариант выглядит скорее как хак. Хочется все-таки найти метод реинициализации каналов Remoting.
Здравствуйте, arhangel, Вы писали:
H>>Ну, вот, разницу ты и сам подтвердил А теперь попробуй чисто в виде экскримента зарегистрить на клиенте объект как Singleton или Singlecall и обратись к нему также, как к серверному объекту: после восстановление линка будет все работать.
A>К сожалению, так не получится – сервер должен работать не с каким-либо объектом, а с конкретным объектом.
Это понятно, я предложил сделать так в виде эксперимента, чтобы ты увидел разницу.
A>На самом деле, если инициализировать сервер в «плохих» условиях, то с ним будет происходить та же ошибка – после восстановления сети клиенты сервер не видят.
Шо значат эти "плохие" условия?
A>Дело в том, что объект для обратной связи на клиенте создается уже после того, как связь восстановиться. До этого у сервера не было никаких ссылок на него, и у клиента тоже.
Само собой
A>Т.е. время жизни здесь не поможет.
Время жизни всегда поможет, когда объект пересекает границы домена. В данном случае именно это и происходит с клиентским MBR'ом.
H>>Более того, если для клиентского MBR'а не переопределен Lifetime (или нет спонсора), то он даже без обрыва линка может умереть после некоторого бездействия.
A>Даже если на него как на локальный объект остались ссылки у других клиентских объектов?
Даже в этом случае. Как только объект пересекает границы домена, ему локальные ссылки на него по барабану. Т.е. ссылка то на него останется, а вот воспользоваться ей сервер уже не сможет.
A> А если этот метод для него переопределить, будет ли GC его собирать, когда на него не останется локальных ссылок?
Если клиентский MBR должен жить на протяжении жизни всего приложения, то сделай ему вечную жизнь, а если нет — то спонсоры решат твою проблему.