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

Вниз

Траблы с TClientSocket внутри DLL   Найти похожие ветки 

 
kot2   (2002-09-19 11:36) [0]

Есть DLL в ней создается объект TClientSocket. Если теперь открыть сокет, то ничего путнего не происходит. Уже в ONLookup значение Active = false. Если еще раз установить его в TRUE, то опять случается OnLookup в котором Active уже сброшен и затем OnConnecting (в нем соотетственно Active тоже нулевой). DLL вызывается из консольного приложения. Где-то раньше попадалось что-то про подобное поведение TClientSocket в многопоточныых приложениях, но найти не могу.
Какие есть мнения?


 
Digitman   (2002-09-19 12:23) [1]


> ничего путнего не происходит


А что "путное" должно происходить ?


> Уже в ONLookup значение Active = false


C чего бы Active д.б. True в этом событии ?


> OnConnecting (в нем соотетственно Active тоже нулевой).


Вполне нормальное состояние


> подобное поведение TClientSocket в многопоточныых приложениях


Какое отношение имеет в дан.случае использование TClientSocket в DLL к мультипоточности ? Поддерживает ли твоя DLL соглашения о мультипоточности ?


 
kot2   (2002-09-19 12:35) [2]

>> ничего путнего не происходит
>А что "путное" должно происходить ?
Ну как обычно
OnLookup - OnConnecting - OnConnect - OnWrite - OnRead - OnDisconect


>> Уже в ONLookup значение Active = false
>C чего бы Active д.б. True в этом событии ?
Дык я же его в true dscnfdkz.!!!

>> OnConnecting (в нем соотетственно Active тоже нулевой).
>Вполне нормальное состояние
Не понял, почему нулевой должен быть?

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


 
Ghost.   (2002-09-19 12:45) [3]

А общая цель какая?


 
kot2   (2002-09-19 12:50) [4]

А цель простая. DLL является составной частью большого комплекса и в ней должен реализовываться сетевой обмен с сервером.


 
Digitman   (2002-09-19 13:30) [5]

>kot2

> Ну как обычно
> OnLookup - OnConnecting - OnConnect - OnWrite - OnRead -
> OnDisconect
Ну да) ... Что ж здесь "непутного"-то ? Какие в этом сомнения ?

> Дык я же его в true dscnfdkz.!!!
Ну и что ? Тип клиента у тебя какой - NonBlocking ? Чего ж ты хочешь ? Соединиться с сервером на другом конце света мгновенно ? Это - нонсенс ! Соединение может стать активным через ощутимый промежуток времени (когда от сервера придет ACK-пакет, а, может, и не придет еще), а ты с какого-то перепугу считаешь, что - хрясь! - и готово, соединились два гнезда мгновенно...

> >> OnConnecting (в нем соотетственно Active тоже нулевой).
> >Вполне нормальное состояние
> Не понял, почему нулевой должен быть?

Потому что Active - признак установленного коннекта. ты событие OnConnect() получил ? Нет ? А какого же ты считаешь что коннект установлен ? Ты ведь для этого анализируешь признак Active = True, не так ли ?


> Ну во первых ее (DLL) вызывают из отдельного потока, и в
> ней самой существует дополнительный поток, который должен
> отслеживать логику работы (сетевого обмена с сервером)

Что значит - "вызывают из отдельного потока" ? Ее грузят из отдельного потока ? Или ее ф-ции (после загрузки в произвольном потоке) вызываются из доп.потока ?

Ты установил в DLL флаг MultiThread = True ?

Получаешь ли ты события OnConnect() или OnError() после установки Active = True ? Как ты обрабатываешь их ? Контролируешь ли, в каком код.потоке вызываются их обработчики ?


 
kot2   (2002-09-19 13:36) [6]

Да сервер не на другом конце света, а на этой же машине!
Да ее грузят разные потоки и вызывают ф-ии из разных потоков.
А событий кроме OnLookup не происходит.
Вот.


 
Digitman   (2002-09-19 13:51) [7]

>kot2


> Да сервер не на другом конце света, а на этой же машине!


И что из этого, по-твоему, следует ? Что метод SetConnected у неблок.клиента будет работать по-иному ?


> Да ее грузят разные потоки и вызывают ф-ии из разных потоков.


А вот это уже не есть хорошо. И это вызывает подозрения.
И что у тебя происходит при загрузке ?


> событий кроме OnLookup не происходит.


Что у тебя творится в OnLookup() ? Какой тек.код.поток ты обнаруживаешь при обработке события ?
На основании чего ты утверждаешь, что прочие события не возникают ? Ты ставишь BP на их begin и не получаешь ни одной точки останова в run-time ?


 
kot2   (2002-09-19 14:32) [8]

Нет, но насколько я понимаю, после OnLookup должно следовать следующее событие, а именно OnConnecting. А у меня тишина. И при этом никаких исключений не вылетает.
У меня сдается впечатление, что TClientSocket не может быть использован внутри DLL. Между прочим DLL вызывается программой компилированной MSVC. Хотя я пробовал и из-под Борланда, то же самое.
Где-то тут грабли зарыты.


 
Digitman   (2002-09-19 14:37) [9]

> kot2

Хочешь помощи - отвечай на вопросы, а не занимайся всякими домыслами.

1. Чем, по-твоему, DLL-модуль отличается от модуля хост-процесса кроме того, что грузится/выгружается по требованию ?

2. + Вопросы от (19.09.02 13:51)


 
kot2   (2002-09-19 14:56) [10]

Отвечаю
1. а как в DLL организован цикл сообщений? В случае с TAplication более менее ясно, а здесь вопросы. Может быть они просто до компонента и не доходят вовсе.
2. загрузка DLL проходит как обычно сначала PROCESS_ATTACH, затем несколько раз THREAD_ATTACH (в зависимости от кол-ва активных потоков).
>Что у тебя творится в OnLookup() ? Какой тек.код.поток ты >обнаруживаешь при обработке события ?
Я, чесно говоря, не знаю какой поток текущий. Я думаю, тот из которого вызываются экспортируемые функции DLL.
>На основании чего ты утверждаешь, что прочие события не >возникают ? Ты ставишь BP на их begin и не получаешь ни одной >точки останова в run-time ?
Нет я ставлю отладочную печать и ее не наблюдаю на консоле.
(Приложение которое грузит DLL и вызываеn ф-ии из нее - консольное и собрано MSVC++)
Спасибо за участие!


 
Ghost.   (2002-09-19 15:28) [11]

Я не знаю, что ты имеешь ввиду под большим комплексом..но я писал DLL в копорых находились целые программы для сетей имевшие несколько сокетов и клиентских и серверных и все работало..правда они мне нужны как плагины тоесть визуальные..а создавал программу с формами, а потом запихивал все в DLL


 
Digitman   (2002-09-19 15:32) [12]

> 1. а как в DLL организован цикл сообщений? В случае с
А никак ! С какого это перепугу компилятор/линкер обязан вставлять в тело будущей DLL при ее генерации без твоего ведома какой-либо код ? В т.ч. - код диспетчера оконных или иных сообщениий ? В случае с TApplication - это понятно : ты как бы разрешил это явно, подключив Forms в состав модулей, есть хэндл автоматически создаваемого невидимого окна, которому компоненты могут адресовать свои сообщения для централизованной обработки. А в случае с DLL ? Там же объект TApplication при определенных опциях сборки может быть совершенно иным, нежели объект того же класса, но - в хост-процессе !

Это вот тебе пища для размышлений...

> 2. загрузка DLL проходит как обычно сначала PROCESS_ATTACH,
> затем несколько раз THREAD_ATTACH (в зависимости от кол-ва
> активных потоков).

Да это понятно)... Что делается у тебя в контексте обработки PROCESS_ATTACH и THREAD_ATTACH ?

> Я, чесно говоря, не знаю какой поток текущий. Я думаю, тот
> из которого вызываются экспортируемые функции DLL.

Ну это разумеется ! Поток, вызвавший экп.ф-цию из модуля - это тот же поток, в котором исполняется тело этой эксп.ф-ции.

А если он не основной, этот поток ? А ты при этом вызываешь некие non-thread-safe-ф-ции в теле вызванной DLL-ф-ции ?

> Нет я ставлю отладочную печать и ее не наблюдаю на консоле.

А что, разве средства отладки DLL даже в таком случае (когда хост-процесс - не процесс Делфи-приложения) кто-то упразднил ? Или они тебе просто неизвестны, раз пользуешь такие примитивные способы контроля при отладке ?



 
Kot2   (2002-09-19 19:33) [13]

>Это вот тебе пища для размышлений...
Дык я на это и грешу, что цикл обработки сообщений отсутствует, поэтому и никаких событий не происходит...

>Что делается у тебя в контексте обработки PROCESS_ATTACH и >THREAD_ATTACH ?
А ничего особенного не делается. Я проверяю текущую версию файла DLL и усе. А что еще нужно?

>А ты при этом вызываешь некие non-thread-safe-ф-ции в теле >вызванной DLL-ф-ции ?
Нет, с этим похоже все впорядке.

>А что, разве средства отладки DLL даже в таком случае (когда >хост-процесс - не процесс Делфи-приложения) кто-то упразднил ? >Или они тебе просто неизвестны, раз пользуешь такие примитивные >способы контроля при отладке ?

Да я вроде как в курсе, да вот беда, что DLL вызывается из приложения написанного на Microsoft Visual C++ (кстати сама DLL писана в среде Borland C++ Builder, но это один черт что Builder, что Delphi) так вот в этом случае почему-то breakpoint"ы установленные в DLL не хотят отрабатываться (если вызывать из Borland"а, то без проблем отрабатываются). Именно по этому я и пользовался отл. выдачью на консоль.

Похоже все-таки нужно каким-то образом организовывать цикл обработки сообщений внутри DLL. Весь вопрос как???
Или прийдется уходить на WinAPI, а не охота, так как в виде отдельного Builder"овского приложения все работает, а вот попытка засунуть этот код в DLL не канает.

Еще раз спасибо за участие.


 
Digitman   (2002-09-20 09:31) [14]

> Kot2 (19.09.02 19:33)

> Дык я на это и грешу, что цикл обработки сообщений отсутствует,
> поэтому и никаких событий не происходит...

Да нет) ... Он присутствует.
Только "крутится" он у тебя в хост-процессе, который знать ничего не знает о том, что TCustomWinSocket в DLL создал собственное невиз.окно для адресации сообщений типа CM_SOCKETMESSAGE, CM_DEFERFREE и СM_LOOKUPCOMPLETE

Вот диспетчер-обработчик этих сообщений :


procedure TCustomWinSocket.WndProc(var Message: TMessage);
begin
try
Dispatch(Message);
except
Application.HandleException(Self);
end;
end;


Другой вопрос, что окно, создаваемое в Forms.AllocateWnd() (см. метод TCustomWinSocket.GetHandle), создается в ином код.потоке нежели осн.окно приложения, цикл обработки сообщений которого "крутится" в осн.потоке и вызов в нем DispatchMessage() не может диспетчеризовать сообщения для окон, созданных в иных потоках.
Вот и получается, что гнездо способно посылать (и - скорее всего - посылает !) win-сообщения, ("зная", куда их посылать - "адрес"-то существует в TCustomWinSocket.Handle), но гл.цикл обработки сообщений хост-процесса не может диспетчеризовать такие сообщения, ибо окна, которым они адресованы, созданы в потоке, отличном от основного.

> А ничего особенного не делается. Я проверяю текущую версию
> файла DLL и усе. А что еще нужно?

Ну как минимум IsMultiThread = True в блоке begin..end dpr-файла твоей DLL. Хотя это и не имеет непоср.отношения к механизму трансляции и обработки оконных сообщений, это нужно делать для корректной работы менеджера памяти от Борланда в условиях мультипоточности.

> >А ты при этом вызываешь некие non-thread-safe-ф-ции в теле
> >вызванной DLL-ф-ции ?
> Нет, с этим похоже все впорядке.

Почему ты так уверен в этом ? Я не имею ввиду только лишь VCL-методы визуальных контролов - мало ли какие неразделяемые ресурсы ты еще задействуешь в контексте доп.потока ! Здесь запросто могут быть грабли ...

> Да я вроде как в курсе, да вот беда, что DLL вызывается
> из приложения написанного на Microsoft Visual C++ (кстати
> сама DLL писана в среде Borland C++ Builder, но это один
> черт что Builder, что Delphi) так вот в этом случае почему-то
> breakpoint"ы установленные в DLL не хотят отрабатываться
> (если вызывать из Borland"а, то без проблем отрабатываются).
> Именно по этому я и пользовался отл. выдачью на консоль.

Но ведь, кажется, Борланд С-Билдер позволяет отлаживать VCL DLL путем Run | Attach to Process, точно так же, как и в Делфи ? Если так, то BP просто обязаны отрабатывать !

> Похоже все-таки нужно каким-то образом организовывать цикл
> обработки сообщений внутри DLL. Весь вопрос как???
> Или прийдется уходить на WinAPI, а не охота, так как в виде
> отдельного Builder"овского приложения все работает, а вот
> попытка засунуть этот код в DLL не канает.


Попробуй использовать ctBlocking-режим работы TClientSocket. В этом случае вызовы транспортных методов объекта будут синхронными с вызывающим код.потоком и ни каких оконных событий не будет. Поскольку работа с TClientSocket у тебя все равно идет в доп.потоке, ctBlocking-режим не будет "тормозить" осн.поток.


 
kot2   (2002-09-20 11:10) [15]

2Digitman
Еще раз спасибо за участие.
>Вот и получается, что гнездо способно посылать (и - скорее >всего - посылает !) win-сообщения, ("зная", куда их посылать -> "адрес"-то существует в TCustomWinSocket.Handle), но. >гл.цикл .обработки сообщений хост-процесса не может >диспетчеризовать такие сообщения, ибо окна, которым они >адресованы, созданы в потоке, отличном от основного
Вот похоже в этом и дело. А как сделать так, чтобы эти события доходили по назначению? В случае отдельного приложения там все более менее понятно, создается цепочка адесатов и они получают извещения о событиях. В случае DLL, которая тем более может вызываться совсем не Борландовским процессом такой финт не получится, надо как-то ручками организовывать доставку. Весь вопрос как???
И еще поскольку у меня в DLL нет формы, то я в качестве Owner для TClientSocket указываю NULL (MySocket = new TClientSocket(NULL)). Это никак не может сказываться?

>Но ведь, кажется, Борланд С-Билдер позволяет отлаживать VCL DLL >путем Run | Attach to Process, точно так же, как и в Делфи ? >Если так, то BP просто обязаны отрабатывать !
Все так и получается, если я вызываю DLL из под Борланда, а вот если из под MSVC++ - то брекпойнты почемуто не отрабатываются (по крайней мере у меня не получается). Но это уже другая песня. Конечно с ними отладка удобнее.

>Попробуй использовать ctBlocking-режим работы TClientSocket. В >этом случае вызовы транспортных методов объекта будут >синхронными с вызывающим код.потоком и ни каких оконных событий >не будет. Поскольку работа с TClientSocket у тебя все равно >идет в доп.потоке, ctBlocking-режим не будет "тормозить" >осн.поток.
Это конечно вариант, но во-первых хотелось бы понять где собака зарыта и как ее откопать, а во-вторых - а зачем мне тогда TClientSocket? Я могу это и на WinAPI реализовать.



 
Digitman   (2002-09-20 12:00) [16]

>
>как сделать так, чтобы эти события доходили по назначению?
>В случае отдельного приложения там все более менее понятно, >создается цепочка адесатов и они получают извещения о событиях. >В случае DLL, которая тем более может вызываться совсем не >Борландовским процессом такой финт не получится, надо как-то >ручками организовывать доставку. Весь вопрос как???

Вникни-ка вот в это - св-во Handle объекта Application, который создается у тебя в DLL при инициализации модуля Forms :


Provides access to the window handle of the main form (window) of the application.

property Handle: HWND;

Description

Use Handle when calling Windows API functions that require a parent window handle. For example, a DLL that displays its own top-level pop-up windows needs a parent window to display its windows in the application. Using the Handle property makes such windows part of the application, so that they are minimized, restored, enabled and disabled with the application.

Note: When writing a DLL that uses VCL forms, assign the window handle of the host EXE’s main window to the DLL’s Application.Handle property. This makes the DLL’s form part of the host application. Never assign to the Handle property in an EXE.


>И еще поскольку у меня в DLL нет формы, то я в качестве Owner >для TClientSocket указываю NULL (MySocket = new TClientSocket
>(NULL)). Это никак не может сказываться?

Отсутствие компонента-владельца никак не сказывается на механизме win-сообщений. Это совершенно разные вещи. И, кстати, никто не заставляет тебя выбирать в кач-ве владельца именно VCL-форму - владельцем м.б. любой объект - наследник TComponent. Компонент-владелец отвечает как минимум за автоматическое уничтожение данного "зависимого" компонента (создаваемого с указанием данного владельца) при собственном разрушении, если "зависимый" компонент нигде не разрушается тобой явно до момента разрушения компонента-владельца.

>Все так и получается, если я вызываю DLL из под Борланда, а вот >если из под MSVC++ - то брекпойнты почемуто не отрабатываются
>(по крайней мере у меня не получается). Но это уже другая >песня. Конечно с ними отладка удобнее.

Ну не может быть такого ! Скажем, я успешно трассирую DLL, построенные в Делфи и используемые хост-процессом IB-сервера, приложение которого в разных версиях-ипостасях построено и в среде MSVC++, и в среде MS C, и в среде Borland C. При этом загрузка DLL и вызов ее ф-ций происходят как раз в доп.потоке хост-процесса. И - никаких проблем с Run | Load../Attach ..

>Это конечно вариант, но во-первых хотелось бы понять где собака >зарыта и как ее откопать, а во-вторых - а зачем мне тогда >TClientSocket? Я могу это и на WinAPI реализовать.

Где "собака зарыта" - я уже тебе сказал , см.выше.
А на WinsockAPI - мороки поболе будет, и делать это ради тех же возможностей, что предоставляет TClientSocket, мне кажется неразумным во многих подобных случаях ...

Вообще-то оч.неплохим компромиссным вариантом - по моему собственному опыту - будет, наверно, реализация транспорта на WinsockAPI, но с использованием альтернативного механизма нотификации о гнездовых событиях - средствами системных event-объектов. Рассмотри в этом плане ф-ции WSAEventCreate, WSAEventSelect, WSAWaitForEvents, WSAEnumNetworkEvents. Ни одна из них не исп-ся в TCustomWinSocket (о чем и говорит "Win" в имени данного базового класса, задействующего оконный механизм нотификации)





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

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

Наверх





Память: 0.54 MB
Время: 0.009 c
3-45720
VikOss
2002-10-23 17:51
2002.11.14
TUpdateQuery


1-45806
Alex4444444444
2002-11-04 11:51
2002.11.14
Относительные линки


1-45880
NeyroSpace
2002-11-05 14:00
2002.11.14
Как узнать какой компонент породил Exception?


3-45771
s_karm
2002-10-25 16:22
2002.11.14
filter


1-45834
Fog
2002-11-05 12:44
2002.11.14
SetLength для параметра...





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский