Я знаю что DCOM это далеко не самый умный выбор для сетевого соединения, но так уж случилось что щас мне надо сделать что-б работало
Общие условие задачи:
— клиент соединяется с сервером через DCOM
— соединение между клиентом и сервером может разрываться, как минимум по следующим причинам:
— клиент умер (GPF)
— физическое соединение (кабель) был разорван
— после соединения, возможно через значительный промежуток времени, соединение может восстанавливаться
Большинство проблем я решил создавая сессионый объект на сервере, и использовуя ::CoDisconnectObject(), когда этот сессионый объект не нужен. Есть еще несколько проблем, надо которыми я работаю, вот одна из них, другие напишу по мере надоедания мне искать ответ самому :):
— если клиент вызывает, сервер и во время обработки вызова, сервер визически перегружают (например нажимая Reset), клиент остается в ожидании ответа — и это навсегда. Есть CoCancelCall, и прочие функции, но мои эксперементы пока не привели к желаемому результату. Есть идеи, как сделать что-бы по timeout'у вызов на клиентской стороне прикращался?
Здравствуйте ZORK, вы писали:
ZORK>- если клиент вызывает, сервер и во время обработки вызова, сервер визически перегружают (например нажимая Reset), клиент остается в ожидании ответа — и это навсегда. Есть CoCancelCall, и прочие функции, но мои эксперементы пока не привели к желаемому результату. Есть идеи, как сделать что-бы по timeout'у вызов на клиентской стороне прикращался?
Гм, насколько я понял CoCancelCall тебе не подходит, он предназначен для того чтобы _попросить_ сервер быстренько вырнуться из вызова, т.е. сервер для этого должен быть жив. Слушай, а с чего ты взял, что DCOM-вызовы не возвращаются по timeout?
Вот, посмотри: http://support.microsoft.com/support/kb/articles/Q255/1/98.ASP
Здравствуйте alexm1202, вы писали:
A>Гм, насколько я понял CoCancelCall тебе не подходит, он предназначен для того чтобы _попросить_ сервер быстренько вырнуться из вызова, т.е. сервер для этого должен быть жив. Слушай, а с чего ты взял, что DCOM-вызовы не возвращаются по timeout?
Во-первых, уточню, у упрожняюсь на между двумя Windows 2000 системами. И я использовал Apartment Thread Model для клиента и сервера.
Ну что не возвращается, я узнал просто — создал client/server DCOM приложение, и сделал так что при вызове клиентом сервера, методе сервера запускается for(;){}, так что он никогда контроль не возвращает. При этом если сервер тормозишь дебагером, то клиент узнает про то что сервер ушел, а вот если тупо нажимаешь Reset на компе, то клиент ничего не замечает. Я в порядке эксперемента пару раз ждал больше 10 минут — и клиент продолжал весеть, даже уже тогда когда компьютер, на котором был DCOM сервер, загружался обратно.
А если верить этой статье — то вроде timeout должен наступать максимум в течение 90 сек., но похоже что-то не так. При чем в других источника MC рассказывает про то что они проверяют DCOM соединение, и если в течение 6 мин (по умолчанию) связь с объектом не восстановится, то они забывают про него — очевидно, для этого случая, это тоже не работает.
Я думаю CoCancelCall может оказаться правильным направлением — так как для того что-бы сказать серевру, что надо прервать обработку вызова, надо к серверу обратиться, и тут должен произойти как минимум RPC timeout. Может я не прав, но похоже что при посто вызове, DCOM посылает сообщение серверу, и сидит в каком-то цикле обработки приходящих сообщении, и ничего больше не проверяет. А так как сервер умирает быстро, и без возможности сообщить клиенту что он отвалил, клиент продолжает сидеть в этом цикле до упора.
Спасибо! — натолкнуло на мысли и эксперементы. Оказалось:
— можно сделать cancel сообщения в ATM, если добавить IMessageFileter::MessagePending и возвращать из него после timeout'а PENDINGMSG_CANCELCALL, но так как MessagePanding вызывается, только тогда когда приходит Windows сообщение, то полезно перед COM-вызовом сделать ::SetTimer(wnd, timeout), что-бы сообщение точно пришло, а то опять будет весеть до бесконечности, особенно если это проиходит в нитке не связанной с видимым окном
— вернулся обратно к эксперементу с CoCancelCall — оказалось, что я был рядом. Выяснилось, что для того что-бы прервать COM команду, надо вызвать CoCancelCall пару раз, кстати такое же наблюдалось с IMessageFileter::MessagePending. Надо полагать, при удаленном вызове есть какая-то внутреняя вложенность вызовов. После того как watchdog нитка стала многократно вызывать CoCancelCall — вызовы стали успешно прерываться. Так что проблема решена
Здравствуйте, ZORK, Вы писали:
ZOR>- вернулся обратно к эксперементу с CoCancelCall — оказалось, что я был рядом. Выяснилось, что для того что-бы прервать COM команду, надо вызвать CoCancelCall пару раз, кстати такое же наблюдалось с IMessageFileter::MessagePending. Надо полагать, при удаленном вызове есть какая-то внутреняя вложенность вызовов. После того как watchdog нитка стала многократно вызывать CoCancelCall — вызовы стали успешно прерываться. Так что проблема решена
Добрый день!
Я занимаюсь подобной проблемой с ::CoCancelCall. В основном меня интересует прерывание (разумеется, корректное) вызова ::CoCreateInstanceEx для создания объекта на удаленной машине если сервер недоступен.
Пока никаких проблем обнаружено не было, т.е. дополнительных вызовов ::CoCancelCall не понадобилось.
Если не трудно, не подскажете, в каких случаях возникают подобные ситуации и что возвращает ::CoCancelCall в таких случаях при первом вызове?
Спасибо.