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

Вниз

Подключение по одному порту, ответ по другому, на основе Indy   Найти похожие ветки 

 
Mx ©   (2005-10-05 10:12) [0]

Здравствуйте, Мастера! К сожалению в сетях я мало, что понимаю, но задачка вроде не сложная, решить ее надо побыстрее.

Суть такова. Пусть имеется два разных приложения: сервер и клиент. Клиент подключается к серверу через определенный порт. Сервер принимает "заказ" и формирует некую структуру, которая в дальнейшем отвечает клиенту, но уже по другому порту.

Я поставил TIdTCPServer и TIdTCPClient, причем сервер сделал службой. Однако, коннекта не получается, метод TIdTCPClient.Connect отображает сообщение "Connection was gra(дальше не помню, а Delphi только дома)...

Вопрос такой: какие компоненты Indy должны быть на клиенте и сервере? Как их настроить, а именно как клиенту получить ответ по другому порту? Ну и желательно понять почему же не происходит коннекта.

Извините за громоздкость вопроса, решить надо быстро.
Спасибо.


 
Digitman ©   (2005-10-05 13:08) [1]


> какие компоненты Indy должны быть на клиенте и сервере?


в данном случае и там и там - один и тот же набор : TIdTCPServer и TIdTCPClient.


> как клиенту получить ответ по другому порту?


клиентское приложение, перед тем как с пом.своего  TIdTCPClient послать запрос серверному приложению, должно активировать свой компонент TIdTCPServer на некоем свободном порту и в своем запросе указать номер этого порта

серверное приложение, активировав свой TIdTCPServer и получив запрос от клиентского приложения, обрабатывает его, формирует результат, через свой  TIdTCPClient свой подключается к TIdTCPServer клиентского приложения (ибо его номер порта был передан в запросе и заведомо известен) и передает данные результата


 
Mx ©   (2005-10-05 13:45) [2]

Эх, а я думал одним клиентом как-то можно обойтись. Значит инициировать передачу может только TIdTCPClient, а принимать TIdTCPServer. Я правильно понял?

Есть еще вопросик: для чего в сервере нужны bindings? Надо ли их задавать? Или достаточно указать порт и вызвать TIdTCPServer.Active?


 
Digitman ©   (2005-10-05 15:34) [3]


> Значит инициировать передачу может только TIdTCPClient,
> а принимать TIdTCPServer. Я правильно понял?


неправильно ты понял.

TIdTCPClient может быть лишь инициатором коннекта к TIdTCPServer, но никак не наоборот.

А после установления коннекта (т.е. канал связи установлен) инициатором передачи м.б. любая из сторон установленного канала связи.

Другая же сторона установленного канала связи вольна в любой момент времени инициировать прием, если она ожидает какие-то данные от противоположной стороны установленного соединения (если та самая противоположная, т.е. потенциально передающая сторона и не думает ничего посылать, то сторона, инициирующая прием будет бесконечно ждать, пока существует коннект)


> для чего в сервере нужны bindings?


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


 
Digitman ©   (2005-10-05 15:43) [4]


> Значит инициировать передачу может только TIdTCPClient,
> а принимать TIdTCPServer. Я правильно понял?


неправильно ты понял.

TIdTCPClient может быть лишь инициатором коннекта к TIdTCPServer, но никак не наоборот.

А после установления коннекта (т.е. канал связи установлен) инициатором передачи м.б. любая из сторон установленного канала связи.

Другая же сторона установленного канала связи вольна в любой момент времени инициировать прием, если она ожидает какие-то данные от противоположной стороны установленного соединения (если та самая противоположная, т.е. потенциально передающая сторона и не думает ничего посылать, то сторона, инициирующая прием будет бесконечно ждать, пока существует коннект)


> для чего в сервере нужны bindings?


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


 
Mx ©   (2005-10-07 10:01) [5]

Угу, все работает. Digitman, большое спасибо!


 
Mx ©   (2005-10-14 10:07) [6]

Вот дошло дело до передачи данных общения клиента с сервером по второму порту. Итак, клиент обратился к сервису через TIdTCPClient, на сервисе TIdTCPServer. Он принял подключение и создал нужный объект, отослал его дескриптор на клиент, получил необходимые параметры и прервал связь. Далее в отдельном потоке, новый объект (созданный сервисом) подключается по другому порту с помощью TIdTCPClient к клиенту. Дошло дело до взаимодействия с любой стороны и тут я тормознул. Как TIdTCPClient "спрашивает" у сервера (WriteLn и т.п.) я вроде понял, а вот как наоборот? Допустим, TIdTCPClient ничего не спросил, висит себе в памяти, всякую лабуду гоняет в цикле. Как отловить, что TIdTCPServer хочет че-то "сказать"? Никаких OnCommandXXX-то нету.


 
Digitman ©   (2005-10-14 10:58) [7]


> всякую лабуду гоняет в цикле


где-то среди этой "циклической лабуды" клиент, например, может предусмотреть вызов ReadLn() .. этот метод позволяет указать произвольный тайм-аут, по истечении которого вызванный метод вернет управление, если за это время в адрес клиента со стороны сервера не поступила строка текста ... о том, что время ожидания строки истекло и можно спокойно продолжить "гнать лабуду", следует судить по пустой строке, возвращенной методом.

все сказанное верно для любой из сторон соединения, будь то сервер или клиент

та из сторон, которая вызвала любой Receive/Read-метод, на весь период исполнения метода становится принимающей стороной ("приемником")

та из сторон, которая вызвала любой Send/Write-метод, на весь период исполнения метода становится передающей стороной ("передатчиком")


 
Mx ©   (2005-10-14 11:49) [8]

Угу, понял. Вот еще вопросик: если у меня до фига таких клиентов, все работают по одному порту и каждый пишет и принимает. Получается надо вводить некий идентификатор? Например, первые четыре байта передаваемого пакета - тот самый дескриптор. Или Винда как-то сама понимает какой программе пришел ответ (что я себе слАбо представляю)?


 
Digitman ©   (2005-10-14 12:14) [9]


> Получается надо вводить некий идентификатор?


зачем ? поясни свою мысль ... хотя бы в псевдокоде ..


> Винда как-то сама понимает какой программе пришел ответ


"Винда" не знает никаких "вопросов/ответов", она при этом оперирует объектами "гнездо" (socket), посредством которых организуются транспортные коммуникации

каждое гнездо ассоциировано  с тем процессом в системе, который это гнездо создал

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

когда сервер активируется, он тоже создает гнездо ("слушающее", т.е. принимающее запросы от клиентских гнезд на подключение)

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

с момента организации очередного транспортного канала (той самой "петли") посылка данных с одного из его концов приведет к доставке данных на другой его конец.

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

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

сходи на http://book.itep.ru

почитай внимательно раздел Winsock - многое, думаю, станет намного понятней


 
Mx ©   (2005-10-14 12:36) [10]

Digitman ©

Мощно задвинул, внушает!

Представим, что есть объекты, они представлены одним классом TApp, но каждый функционирует в отдельном потоке (но в одном процессе, в данном случае сервиса). Почему я имел ввиду идентификаторы? Вот допустим этот объект вызывает ReadLn, потом другой тоже. В ответ клиент че-то вякает. Так вот я и думаю, как в приемнике определить: а тот ли клиент ответил...
эээ т.е. TApp проверит "а мне ли пришли данные". Судя по ликбезу, такой проблемы не возникнет, да? (клиенты - самостоятельные процессы).


 
Digitman ©   (2005-10-14 13:23) [11]


> Mx ©   (14.10.05 12:36) [10]



> Представим, что есть объекты, они представлены одним классом
> TApp


т.е. каждый такой объект д.б. ассоциирован со своим клиентом ?


> каждый функционирует в отдельном потоке


а вот здесь мне не понятно ..

объект НЕ может "функционировать в .. потоке", это - носенс

напротив - в потоке (том или ином) можно обратиться к методам/свойствам того или иного объекта (собственно не иначе как в каком-либо код.потоке эти обращения и происходят)

разница есть ?

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

и следом еще вопрос : в каком месте кода сервера создаются объекты класса TApp ?


 
Mx ©   (2005-10-14 13:45) [12]


> Digitman ©


Ну знаю, я знаю, что "объект НЕ может "функционировать в .. потоке"". Выразился так, потому что по сути они выполняют обработку команд - эта самая обработка ведется в отдельном потоке. Каждый из них - самостоятельный субъект, не обращающий внимание на другого, и взаимодействующий с сервисом посредством синхронизации (на event"ах), поэтому мне проще представить, что каждый работает в своем потоке.


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

Ну, во-первых, он не только занимается обработкой команд, он может выполнять действия и без всякого клиента, сам по себе. Более того, и клиент и сервер реализуются одним классом, который определяет ведомый он или ведущий.

Утверждение т.е. каждый такой объект д.б. ассоциирован со своим клиентом ? верно.


 
Mx ©   (2005-10-14 13:57) [13]


> и следом еще вопрос : в каком месте кода сервера создаются
> объекты класса TApp ?

О, забыл ответить! При получении события события TIdTCPServer.OnConnected. Конструктор ничего потокозависимого не выполняет, лишь инициализация парочки полей. Гм... сейчас подумал: а ведь конструктор в ведомом варианте создает TIdTCPClient! Надо выделить в потоковый метод. После OnConnected сервис ожидает приходя определенной команды и затем сообщает мэнеджеру этих самых объектов (назовем TAppMan) о том, что "пора работать". Мэнеджер создает новый поток, в конструкторе передавая указатель на TApp. В Execute этого потока вызовется метод, ну скажем TApp.Work, который произведет фактическую инциализацию и подключится к клиенту по новому порту. Примерно, так.


 
Digitman ©   (2005-10-14 14:04) [14]

по-моему, ты замесил жуткую кашу между прикладным и транспортным логическими уровнями, и теперь сам не можешь в ней разобраться)

начни с того, отдели мух от котлет, т.е. разнеси транспортную и прикладную функциональность по разным объектам

TIdTCPServer/Client - это ТРАНСПОРТНЫЙ уровень, его задача - ожидать/принимать/передавать инф.сообщения ... прикладной же обработкой принятых сообщений (с формированием результата обработки) должен заниматься другой, прикладной уровень, который как раз и м.б. реализован в виде какого-то объекта а-ля TRequestProcessor ... этот самый TRequestProcessor не должен наниматься ничем иным, как только получать от транспортного уровня полученный им запрос, исполнять его и возвращать, если необходимо, транспортному уровню результат процессинга запроса для передачи его запрашивающей стороне соединения.

Иными словами, сервер с каждым своим клиентом должен работать в циклическом режиме "жду запроса - получил запрос - обработал запрос - вернул ответ"


 
Mx ©   (2005-10-14 14:17) [15]


> Digitman ©

Дык, разве у меня не так? TIdTCPClient/Server общаются, а TApp обрабатывает. Не понимаю, что не так, разъясни пожалуйста. Возникает вопрос: в каком потоке Indy-компоненты будут генерировать события?


 
Digitman ©   (2005-10-14 15:02) [16]


> разве у меня не так? TIdTCPClient/Server общаются, а TApp
> обрабатывает. Не понимаю, что не так


я тогда тоже не понимаю, что ты имел ввиду под


> он не только занимается обработкой команд, он может выполнять
> действия и без всякого клиента, сам по себе. Более того,
>  и клиент и сервер реализуются одним классом, который определяет
> ведомый он или ведущий


первое, что приходит в голову, это тот самый упомянутый тобой TApp, который занимается черт-те чем - и транспортом, и прикладными делами, и еще черт-те чем и с боку с бантиком)

вот как ты всю эту бодягу описал, так я ее и воспринял)


> в каком потоке Indy-компоненты будут генерировать события?


смотря какие события ..

и смотря о каком Indy-компоненте речь идет ... (версия Инди ? 9 ? 10 ? иная ?)

по кр.мере в 9-ке тело обработчика события OnExecute() выполняется в доп.потоке, ассоциированном с объектом класса TIdPeerThread, ссылка на которы как раз и передается факт.параметром AThread в процедуру-обработчик этого события.


 
Mx ©   (2005-10-14 16:25) [17]


> Digitman ©  


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

Огромнейший тебе мегареспект!



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

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

Наверх





Память: 0.52 MB
Время: 0.039 c
4-1131538341
Spose
2005-11-09 15:12
2006.01.22
Скрыть окно чужого приложения


1-1134687807
Батала
2005-12-16 02:03
2006.01.22
Как определить какая кнопка нажата (не путать с символами)?


14-1135769635
Johnmen
2005-12-28 14:33
2006.01.22
Модераторам


2-1135807881
saNat
2005-12-29 01:11
2006.01.22
Требуется помощь в поиске ошибки


14-1134829873
Piter
2005-12-17 17:31
2006.01.22
Чистосердечное признание





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