.NET Remoting
От: arhangel  
Дата: 03.10.05 18:23
Оценка:
Привет!

Кто-нибудь сталкивался с подобной проблемой:

При инициализации клиентского приложения, использующего Remoting, в условиях диагностированной поломки в сети (выдернут кабель из карты и горит соответствующий значок или сетевое соединение вообще отключено через Control Panel\Network and Dial-up Connection), после восстановления сетевого соединения вызовы к серверным методам проходят нормально, но при попытке сервера обратится к клиентскому интерфейсу обратной связи выскакивает ошибка: «No connection could be made because target machine actively refuse it». Причем в случае если поломка не диагностирована явно (серверное приложение не запущено или нет доступа к серверной машине, но сама сеть есть), все работает нормально – после восстановления связи вызовы и от клиента к серверу, и от сервера к клиенту идут нормально.

Пробовал повторно инициализировать Remoting – сначала удалял все каналы, а потом снова создавал в новых условиях, но это не помогает и приходится все равно перезапускать клиентское приложение целиком.

Буду очень признателен, за идеи – как заставить Remoting заново инициализироваться без перезапуска приложения, или каким-либо другим способом решить вышеописанную проблему.

Спасибо.
Re: .NET Remoting
От: oleksab Украина  
Дата: 04.10.05 07:32
Оценка:
Здравствуйте, arhangel, Вы писали:

A>При инициализации клиентского приложения, использующего Remoting, в условиях диагностированной поломки в сети (выдернут кабель из карты и горит соответствующий значок или сетевое соединение вообще отключено через Control Panel\Network and Dial-up Connection), после восстановления сетевого соединения вызовы к серверным методам проходят нормально, но при попытке сервера обратится к клиентскому интерфейсу обратной связи выскакивает ошибка: «No connection could be made because target machine actively refuse it».


А что показывает netstat — порт на клиенте открыт?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Re: .NET Remoting
От: GlebZ Россия  
Дата: 04.10.05 07:40
Оценка:
Здравствуйте, arhangel, Вы писали:

stack trace показать можешь?

С уважением, Gleb.
ЗЫ у меня такое было, но из-за обрыва коннекта с БД.
Re: .NET Remoting
От: hugo Австрия  
Дата: 04.10.05 09:04
Оценка:
Здравствуйте, arhangel, Вы писали:

Как зарегистрированы объекты на сервере? Небось 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>Как сервер знает о клиенте? Небось передали ссылку на клиентский объект? Если да, то не будет работать коллбэк, пока снова не получите на сервере валидную ссылку на клиентский объект.


Ссылка передается свеженькая на новый объект по новому каналу, другое дело, что серверная часть клиентского канала не принимает соединение при попытке обратится к объекту с сервера.
Re[3]: .NET Remoting
От: hugo Австрия  
Дата: 04.10.05 10:02
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, 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>ЗЫ у меня такое было, но из-за обрыва коннекта с БД.

Сори за тормоза — у нас инет отваливался...

Вот так выгляди стэк вызовов (лучше смотреть снизу вверх):



А вот тут и происходит облом — не удается соединится с клиентским приложением так как у него битый канал...

system.dll!System.Net.Sockets.Socket.Connect(System.Net.EndPoint remoteEP) + 0x151 bytes
system.runtime.remoting.dll!System.Runtime.Remoting.Channels.RemoteConnection.CreateNewSocket() + 0x40 bytes
system.runtime.remoting.dll!System.Runtime.Remoting.Channels.SocketCache.GetSocket(string machineAndPort) + 0xaf bytes
system.runtime.remoting.dll!System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.SendRequestWithRetry(System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders requestHeaders, System.IO.Stream requestStream) + 0x61 bytes
system.runtime.remoting.dll!System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.ProcessMessage(System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders requestHeaders, System.IO.Stream requestStream, System.Runtime.Remoting.Channels.ITransportHeaders responseHeaders, System.IO.Stream responseStream) + 0x10 bytes
system.runtime.remoting.dll!System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage msg) + 0x63 bytes
mscorlib.dll!System.Runtime.Remoting.Proxies.RemotingProxy.CallProcessMessage(System.Runtime.Remoting.Messaging.IMessageSink ms, System.Runtime.Remoting.Messaging.IMessage reqMsg, System.Runtime.Remoting.Contexts.ArrayWithSize proxySinks, System.Threading.Thread currentThread, System.Runtime.Remoting.Contexts.Context currentContext, bool bSkippingContextChain) + 0x62 bytes
mscorlib.dll!System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(System.Runtime.Remoting.Messaging.IMethodCallMessage reqMcmMsg, bool useDispatchMessage, int callType) + 0x28d bytes
mscorlib.dll!System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage reqMsg) + 0x113 bytes
mscorlib.dll!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData msgData, int type) + 0x288 bytes

Внутри этого метода происходит обращение к одному из методов объекта dataReceiver

myserver.dll!MyServer.Session.CreateRequest(System.Xml.XmlReader requestXml = {System.Xml.XmlTextReader}, CommonTypes.IDataReceiver dataReceiver = {System.Runtime.Remoting.Proxies.__TransparentProxy}, System.Guid requestGuid = {System.Guid}) + 0x151 bytes

Это тот самый метод, который дернул клиент (ссылка на интерфейс обратной связи
представлена в виде TransparentProxy, но это все прозрачно и для клиента,
и для сервера)

myserver.dll!MyServer.Server.ProceedRequest(string requestXml = "текст запроса", System.Guid sessionGuid = {System.Guid}, CommonTypes.IDataReceiver dataReceiver = {System.Runtime.Remoting.Proxies.__TransparentProxy}, System.Guid requestGuid = {System.Guid}) + 0x10b bytes

Это remoting работает на получении вызова от клиентского приложения в сервере:

mscorlib.dll!System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage msg, int methodPtr, bool fExecuteInContext) + 0x30b bytes
mscorlib.dll!System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage msg) + 0x9 bytes
mscorlib.dll!System.Runtime.Remoting.Messaging.ServerObjectTerminatorSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage reqMsg) + 0x12c bytes
mscorlib.dll!System.Runtime.Remoting.Messaging.ServerContextTerminatorSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage reqMsg) + 0x1b3 bytes
mscorlib.dll!System.Runtime.Remoting.Channels.CrossContextChannel.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage reqMsg) + 0x209 bytes
mscorlib.dll!System.Runtime.Remoting.Channels.ChannelServices.DispatchMessage(System.Runtime.Remoting.Channels.IServerChannelSinkStack sinkStack, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Messaging.IMessage replyMsg) + 0x22c bytes
mscorlib.dll!System.Runtime.Remoting.Channels.DispatchChannelSink.ProcessMessage(System.Runtime.Remoting.Channels.IServerChannelSinkStack sinkStack, System.Runtime.Remoting.Messaging.IMessage requestMsg, System.Runtime.Remoting.Channels.ITransportHeaders requestHeaders, System.IO.Stream requestStream, System.Runtime.Remoting.Messaging.IMessage responseMsg, System.Runtime.Remoting.Channels.ITransportHeaders responseHeaders, System.IO.Stream responseStream) + 0x31 bytes
system.runtime.remoting.dll!System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(System.Runtime.Remoting.Channels.IServerChannelSinkStack sinkStack, System.Runtime.Remoting.Messaging.IMessage requestMsg, System.Runtime.Remoting.Channels.ITransportHeaders requestHeaders, System.IO.Stream requestStream, System.Runtime.Remoting.Messaging.IMessage responseMsg, System.Runtime.Remoting.Channels.ITransportHeaders responseHeaders, System.IO.Stream responseStream) + 0x3e6 bytes
system.runtime.remoting.dll!System.Runtime.Remoting.Channels.Tcp.TcpServerTransportSink.ServiceRequest(System.Object state) + 0xe1 bytes
system.runtime.remoting.dll!System.Runtime.Remoting.Channels.SocketHandler.ProcessRequestNow() + 0x28 bytes
system.runtime.remoting.dll!System.Runtime.Remoting.Channels.RequestQueue.ProcessNextRequest(System.Runtime.Remoting.Channels.SocketHandler sh) + 0x18 bytes
system.runtime.remoting.dll!System.Runtime.Remoting.Channels.SocketHandler.BeginReadMessageCallback(System.IAsyncResult ar) + 0x81 bytes
system.dll!System.Net.Sockets.OverlappedAsyncResult.CompletionPortCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* nativeOverlapped) + 0x13c bytes
Re[4]: .NET Remoting
От: arhangel  
Дата: 04.10.05 11:57
Оценка:
Здравствуйте, hugo, Вы писали:

H>>>Как сервер знает о клиенте? Небось передали ссылку на клиентский объект? Если да, то не будет работать коллбэк, пока снова не получите на сервере валидную ссылку на клиентский объект.


А>>Ссылка передается свеженькая на новый объект по новому каналу, другое дело, что серверная часть клиентского канала не принимает соединение при попытке обратится к объекту с сервера.


H>Ну, вот, разницу ты и сам подтвердил А теперь попробуй чисто в виде экскримента зарегистрить на клиенте объект как Singleton или Singlecall и обратись к нему также, как к серверному объекту: после восстановление линка будет все работать.


К сожалению, так не получится – сервер должен работать не с каким-либо объектом, а с конкретным объектом. В данном случае именно с тем, ссылку на который передал клиент. На самом деле, если инициализировать сервер в «плохих» условиях, то с ним будет происходить та же ошибка – после восстановления сети клиенты сервер не видят. При этом если сервер был инициализирован при нормальной сети, а потом произошел разрыв, после восстановления сетки клиенты соединяются с ним нормально. Просто для сервера эта ситуация не критична.

H>Можно еще как и раньше передавать его (клиентский MBR) на сервер, но время жизни вечное сделать. Тоже все должно быть ок после восстановления связи.


Дело в том, что объект для обратной связи на клиенте создается уже после того, как связь восстановиться. До этого у сервера не было никаких ссылок на него, и у клиента тоже. Т.е. время жизни здесь не поможет.

H>Более того, если для клиентского MBR'а не переопределен Lifetime (или нет спонсора), то он даже без обрыва линка может умереть после некоторого бездействия.


Даже если на него как на локальный объект остались ссылки у других клиентских объектов? А если этот метод для него переопределить, будет ли GC его собирать, когда на него не останется локальных ссылок?
Re: .NET Remoting
От: arhangel  
Дата: 04.10.05 11:58
Оценка:
Привет!

Пока удалось решить проблему следующим образом – перед созданием канала Remoting идет попытка соединения с указанным в URI сервером с помощью простого TcpClient. Если попытка успешна, то канал открывается и все работает. Т.е. получается так, что при отсутствии сети канал не будет инициализироваться.
Однако такой вариант выглядит скорее как хак. Хочется все-таки найти метод реинициализации каналов Remoting.

Спасибо
Re[5]: .NET Remoting
От: hugo Австрия  
Дата: 05.10.05 07:03
Оценка:
Здравствуйте, arhangel, Вы писали:

H>>Ну, вот, разницу ты и сам подтвердил А теперь попробуй чисто в виде экскримента зарегистрить на клиенте объект как Singleton или Singlecall и обратись к нему также, как к серверному объекту: после восстановление линка будет все работать.


A>К сожалению, так не получится – сервер должен работать не с каким-либо объектом, а с конкретным объектом.

Это понятно, я предложил сделать так в виде эксперимента, чтобы ты увидел разницу.

A>На самом деле, если инициализировать сервер в «плохих» условиях, то с ним будет происходить та же ошибка – после восстановления сети клиенты сервер не видят.

Шо значат эти "плохие" условия?

A>Дело в том, что объект для обратной связи на клиенте создается уже после того, как связь восстановиться. До этого у сервера не было никаких ссылок на него, и у клиента тоже.

Само собой

A>Т.е. время жизни здесь не поможет.

Время жизни всегда поможет, когда объект пересекает границы домена. В данном случае именно это и происходит с клиентским MBR'ом.


H>>Более того, если для клиентского MBR'а не переопределен Lifetime (или нет спонсора), то он даже без обрыва линка может умереть после некоторого бездействия.


A>Даже если на него как на локальный объект остались ссылки у других клиентских объектов?

Даже в этом случае. Как только объект пересекает границы домена, ему локальные ссылки на него по барабану. Т.е. ссылка то на него останется, а вот воспользоваться ей сервер уже не сможет.

A> А если этот метод для него переопределить, будет ли GC его собирать, когда на него не останется локальных ссылок?

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