Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.02.03;
Скачать: [xml.tar.bz2];

Вниз

COM/DCOM   Найти похожие ветки 

 
GrEG   (2003-01-22 12:36) [0]

С помощью стандартного мастера создаю приложение-сервер с событиями (обратные вызовы). Дописываю необходимый код, реализующий функциональность. Регистрирую сервер. Создаю приложение-клиент, выполняю Import TypeLibrary с формированием компонента-оболочки. Кидаю полученный компонент на форму, пишу обработчики событий сервера. Настраиваю DCOM с помощью dcomcnfg (для упрощения разрешаю запускать и работать с сервером с полными правами всем пользователям).
Программа, которую я делаю, - чат на базе DCOM - испытательный полигон для изучения COM. Естественно, возникают вопросы, а именно:
Запускаю клиента, подключаюсь к удаленному серверу, регистрирую клиента (моя процедура, обеспечиваю уникальность ников). Отправляю сообщения, они нормально обрабатываются сервером и возвращаются через события для отображения на стороне клиента. На том же компьютере запускаю второго клиента. Он тоже нормально регистрируется на сервере и обрабатывает сообщения. Вот тут и срабатывает НО: складывается впечатление, что для каждого клиента запускается свой сервер, уже присутствующий в чате клиент(ы) не получает уведомлений о подключении/отключении новых клиентов и, соответственно, не получает сообщений. Это тем более странно, что на компьютере, где находится приложение-сервер, запущена только одна копия сервера (смотрел через список процессов). Не может подключиться к запущенному удаленно серверу и клиент, находящийся на том же компьютере, что и сервер. По-видимому, для него тоже создается своя копия сервера.
Клиент - WinNT4 Server, сервер - Win2K Pro. Просьба не обсуждать расположение клиента и сервера, на 2K у меня установлен Delphi.


 
Digitman   (2003-01-22 13:00) [1]

Как ты регистрируешь фабрику класса COM-сервера ? С какими параметрами Instancing и ThreadingModel ?


 
GrEG   (2003-01-22 13:25) [2]

ciMultiInstance и tmApartment


 
Digitman   (2003-01-22 13:39) [3]

Ну так а что ж ты хочешь ? При ciMultiInstance каждый клиент (контроллер), обращаясь к зарегистрированной таким образом фабрике класса, получает отдельный экземпляр сервера.

Переделывай на ciSingleInstance и tmFree


 
Набережных С.   (2003-01-22 16:14) [4]

>GrEG

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


 
GrEG   (2003-01-23 08:28) [5]

Спасибо


 
GrEG   (2003-01-23 08:42) [6]

2 Digitman:
Попробовал сделать, ка кты написал. При попытке подключения второго клиента выдает ошибку "The RPC server is unavailable".
И потом, в хелпе написано следующее:
ciSingleInstance
Allows only a single instance of the COM object for each executable (application). If this single instance is not shared across multiple clients, then each client must launch its own instance of the executable.

ciMultiInstance
The COM object is created as one of multiple instances within the same executable. Any time a client requests service, a separate instance of the object gets invoked.
Если я с мои не очень продвинутым знанием английского правильно понял, то именно ciSingleInstance заставляет создавать для каждого клиент собственную копия сервера. Правда, только если он не расшарен (каким образом?)


 
Digitman   (2003-01-23 09:32) [7]

ciSingleInstance

Allows only a single instance of the COM object for each executable (application). If this single instance is not shared across multiple clients, then each client must launch its own instance of the executable

Позволяет создавать только один экземпляр объекта для каждого стартуемого системой (по запросу контроллера) процесса сервера. Если этот единственный экземпляр не настроен (средствами DCOM-конфигуратора) на работу в режиме разделения между всеми потенциальными клиентами-контроллерами, то каждый клиент-контроллер в результате запроса получит отдельный (стартуемый механизмом DCOM) процесс сервера и отдельный экз-р объекта, созданный этим стартованным процессом сервера.

p.s. если DCOM-конфигуратором сервер настроен для создания разделяемого объекта, то при tmApartmemt обращения разных клиентов к объекту будут сериализованы, иначе обращения разных клиентов будут параллельны в отдельных код.потоках.

ciMultiInstance

The COM object is created as one of multiple instances within the same executable. Any time a client requests service, a separate instance of the object gets invoked.

СОМ-объект создан как один из множества экз-ров в контексте одного и того же процесса-сервера. В любой момент, когда любой клиент-контроллер требует от (одного и того же !) серверного процесса создания СОМ-объекта, для него серверным процессом создается отдельный экз-р объекта, к методам/св-вам которого будет обращаться только данный клиент

p.s. опять же большое значение имеет св-во ThreadingModel - либо все запросы всех клиентов ко всем своим экземплярам сериализуются в контексте осн.код.потока процесса сервера, либо запроосы выполняются параллельно в код.потоках, которые по своему усмотрению диспетчеризует COM-механизм.

p.p.s.

Если процесс сервера единственный (ciMultiInstance), то он вполне может видеть и контролировать ВСЕ экземпляры объектов, создаваемые фабрикой класса без специально принимаемых мер, ибо ВСЕ экз-ры объектов находятся в одном и том же вирт.адр.пространстве. Иными словами, ход создания/уничтожения/использования RDM-объектов можно контролировать на уровне хотя бы событий TRemoteDataModule


 
GrEG   (2003-01-23 11:15) [8]

Спасибо за разъяснения.
Но откуда тогда появляется ошибка "The RPC server is unavailable" при удаленном вызове при подключении второго клиента? Получается, что создается один COM-объект, но и доступ к нему может получить только один клиент, не смотря на tmFree (по край ней мере удаленно, локально можно модключить несколько клиентов и все работает). А это как бы не совсем то, что нужно.

Кроме того, по ходу пьесы всплыл еще один вопрос. В интерфейсе событий создается метод, который содержит var-параметр, т.е. клиент должен вернуть какие-то данные серверу. В моем случае, сервер шлет запрос клиенту для получения его ника по имеющемуся интерфейсу. Соответствие ник-интерфейс можно получить и по другому - просто при регистрации очередного клиента в списке хранить его ник и интерфейс обратного вызова, но мне интересен именно этот вариант. Так вот, на клиентской стороне событие отрабатывается и в параметр записывается необходимая информация. Вместо реального ника, сервер получает пустую строку. Полез в исходники. Смотрим TServerEventDispatch.Invoke в модуле OleServer. При обработке события от сервера параметры переписываются в VarArray:TVariantArray из нетипизированной переменной Params (как впоследствии выясняется имеющей тип TDispParams). Вызывается метод InvokeEvent сервера, а потом результаты изменений со стороны клиента ПРОСТО СТИРАЮТСЯ:

SetLength(VarArray,0);

Каким же образом можно вернуть значения серверу? Выходит, что Delphi плюет на указанный в TypeLibrary спецификатор "var". Попытался ручками подправить код, чтобы вернуть значения серверу. Не тут-то было. Получаем ошибку "Неверно задана вызываемая сторона". Как быть в этом случае?


 
GrEG   (2003-01-23 13:33) [9]

Вот код, которым я пытаюсь записать в Params изменения, сделанные клиентом.

for I := Low(VarArray) to High(VarArray) do
OleVariant(TDispParams(Params).rgvarg^[I]):=VarArray[High(VarArray)-I];


 
GrEG   (2003-01-23 13:46) [10]

Ответ можно и на e-mail.


 
GrEG   (2003-01-24 07:56) [11]

Up



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2003.02.03;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.011 c
14-5174
Дмитрий К.К.
2003-01-18 10:02
2003.02.03
Именинники 18 января


1-5041
ЮРИЙ_К
2003-01-23 15:45
2003.02.03
Снимок экрана в JPG


1-4863
HP
2003-01-24 16:20
2003.02.03
Меню XP


14-5170
gsu
2003-01-16 18:06
2003.02.03
Как посчитать количество строк кода, если имеется около


1-4964
volentin
2003-01-23 17:49
2003.02.03
как текст из файла txt поместить в буфер array





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский