![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TServerSocket, TClientSocket. Синхронный и асинхронный, блокирующ [D6, Win95/98, WinME, NT4, Win2k, WinXP]
Анонимщик © (2004-04-22 11:33:00)Синхронный и асинхронный, блокирующий и неблокирующий.
Что в контектсе сокетов значит "Синхронный и асинхронный, блокирующий и неблокирующий"?
Я почему-то думал, что синхронный режим - тот, что позволяет обеим сторонам общаться,
синхронизируя посылку данных друг другу. Т.е. работа в синхронном режиме подразумевает
некий диалог между ними.
Но вот читаю: "Асинхронными они названы по той причине, что их выполнение связано с
определенным диалогом и ни начало, ни завершение не ограничено какими-либо временными
рамками". Т.е. с точностью до наоборот. Почему так, можно спросить?
Далее, если асинхронный режим тот, что подразумевает диалог, а не просто пересылку данных
любой их сторон другой стороне, то, выходит, асинхронный режим - блокирующий, т.е.
одна из сторон на время своего посылания данных блокирует другую?
И еще одно. Если режим асинхронный, то тогда нужно выставить тип для сервера - ctThreadBlocking,
а для клиента - ctBlocking? Тогда сервер для каждого клиентского соединения создает поток,
который с этим клиентом и работает. И вот мне не понятно, почему того же нельзя сделать
и для синхронного режима в принципе, т.е. почему нет этой возмодности.
Короче, я все напутал, прошу помочь распутать.
И последнее. Можно ли создавать TClientSocket не в главном потоке? Прочитал, что операционная
система сообщает о событиях для сокета в то окно, с контекстом потока которого сокет связан.
Естественно, в дочернем потоке никакого окна нет. Так дойдет ли куда-нибудь сообщение вообще?
Впрочем, так я уже делал, но, кроме этого, создавал еще и поток, который занимается обработкой
принимаемых/отправляемых данных для этого сокета. И данные приходят и отправляются. Но смутные
сомнения терзают все равно.
Короче говоря, пожалуйста, те, кто знают, пусть разжуют, правильно сформулируют и ответят.
Rouse_ (2004-04-23 23:08:00) [21]Type Parameter
Syntax {$EXTERNALSYM identifier}
The EXTERNALSYM directive prevents the specified Pascal symbol from appearing in header files generated for C++Builder. If an overloaded routine is specified, all versions of the routine are excluded from the header file.
Piter (2004-04-23 23:06:00) [22]А можно попутный вопрос? Зачем нужна директива $EXTERNALSYM ?
Verg (2004-04-23 19:04:00) [23]
type
{$EXTERNALSYM u_char}
u_char = Char;
{$EXTERNALSYM u_short}
u_short = Word;
{$EXTERNALSYM u_int}
u_int = Integer; {$EXTERNALSYM u_long}
u_long = Longint;
{ The new type to be used in all
instances which refer to sockets. }
{$EXTERNALSYM TSocket}
TSocket= u_int;
"Гемор", говоришь...
Verg (2004-04-23 19:01:00) [24]
> В Делфи7 Борланд вообще их переделала - по новой разбираться
> с ними - пустая трата времени.
Пере.. что? Куда переделала, какие именно "компоненты" переделала?
TSocket - это тип данных из модуля WinSock.pas. По-сути - integer.
Ермак (2004-04-23 18:44:00) [25]Вообще рекомендую бросить работать с компонентами типа TSocket - это такой гемор! В Делфи7 Борланд вообще их переделала - по новой разбираться с ними - пустая трата времени. Есть WinSock API, все просто и понятно, я за полчаса с ним разобрался и начал работать. Можно создавать сколько хочешь потоков, хоть с окном, хоть без окна, хоть в сервисе - дело хозяйское, ты все полностью контролируешь и понимаешь. Особенно если поток создавать не тупым TThread, а через Create Thread. Короче, рекомендую WinSock API и вообще код, чистый от компонентов!
Вот хорошая статья: http://book.itep.ru/7/sock_71.htm
Digitman (2004-04-23 16:48:00) [26]
> Yermek (23.04.04 16:24) [20]
либо закрыть все активные соединения (в списке Connections) ,прежде чем делать ServerSocket.Close, либо изменить радикальным образом явно неверный алгоритм метода ClientExecute
в любом случае то что творится в ClientExecute
заслуживает детального рассмотрения
Yermek (2004-04-23 16:24:00) [27]Как корректно закрыть ServerSocket (stThreadBlocking) если к нкму подключены ClientSocket, при ServerSocket.Close пограмма зависает.
Digitman (2004-04-23 08:58:00) [28]
> Fantasist © (23.04.04 01:39) [17]
> Неблокирующий вызов - это все-таки не вызов процедуры с
> отложенным получением данных путем уведомления (это как
> раз асинхронный вызов), а вызов, который возращается в независимости
> были ли полученны данные или нет
вникни в [3]
как раз об этом я там и сказал
в чем же расхождение ?
> объясняются следствия (работа TClietSocket/TServerSocket
> и их опции), а не факты их порождающие (WinSocket API).
а какая разница, WinSock API или не WinSock API ? оболочка (в виде упомянутых компонентов) или не оболочка ? Суть от этого не меняется. Есть просто некий вызов, он м.б. блокирующим, а может быть и неблокирующим - в зависимости от реализации алгоритмов вызываемого кода. Если внутренний алгоритм вызыв.п/программы предусматривает асинхронные нотификации (тем или иным образом), его можно использовать, а можно и не использовать, если задействован неблок.механизм вызываемого алгоритма.
в случае с оболочкой WinSock API в виде упомянутых компонентов все так же остается в силе
например, тот же вызов метода Open() в неблок.режиме практически немедленно вернет управление, создав перед этим (если требуется) окно, связав окно с гнездом и запустив механизм коннекта...
чтобы получить асинхр.извещение о факте коннекта, достаточно назначить обработчик события OnConnect ... если же асинхр.извещение о факте коннекта не требуется, придется циклически опрашивать состояние св-ва Active, при этом не забывая в каждой итерации на время передавать управление диспетчеру оконных сообщений (коль мы точно знаем, что внутренняя нотификация как таковая все равно задействована, хотим мы этого или нет , и именно - оконная)
Polevi (2004-04-23 07:59:00) [29]>Yermek (22.04.04 21:46) [16]
отдельный поток для асинхронного режима как раз не обязателен для каждого нового клиента. достаточно одного кодового потока, который будет принимать уведомления от winsock о неких событиях (получение данных, акцепт клиента, дисконнект) и чтото делать. главное чтобы эти действия занимали как можно меньше времени, чтобы не блокировать транспорт
Fantasist (2004-04-23 01:39:00) [30]
> Digitman © (22.04.04 12:06) [1]
Не совсем могу согласиться с приведенной аналогией блокирующего/неблокирующего вызова. Неблокирующий вызов - это все-таки не вызов процедуры с отложенным получением данных путем уведомления (это как раз асинхронный вызов), а вызов, который возращается в независимости были ли полученны данные или нет. Сравнить можно с проверкой е-мыльного ящика:
1. Блокирующий. Ты открываешь почтового клиента, и ничего не делаешь, пока в нем не появиться новое письмо. После этого ты его читаешь и начинаешь что-то делать.
2. Неблокирующий. Открываешь почтового клиента и смотришь: если есть письмо - читаешь его и начинаешь что-то делать, если нет, продолжаешь заниматься чем-то другим.
Хочу сказать, что объяснения приеведенные в это треде весьма запутывающе. Думаю как раз из-за того, что объясняются следствия (работа TClietSocket/TServerSocket и их опции), а не факты их порождающие (WinSocket API). Я бы реккомендовал поизучать работу с сокетами непосредственно на уровне API, тогда станет понятно, что за "асинхронный режим работы", и что делает stThreadBlocking и stNonBlocking. А так же может выясниться, что TClietSocket/TServerSocket вовсе и не нужны. Со мной во всяком случае так и произошло на серверной части. Оказалось, что мне удобнее и надежнее написать собственную реализацию класса серверного сокета используя API, нежели использовать готовую от Delphi.
Yermek (2004-04-22 21:46:00) [31]"Краткость сестра таланта"
Sorry за назойлевость.
Как в асинхронном элементарно текстовое сообщение отправить от сервера к клиенту и наоборот, я в курсах что создается отдельный поток на сервере при каждом новом подключении клиента... а можно пример.
Polevi (2004-04-22 21:29:00) [32]> [14] Yermek (22.04.04 20:53)
нет
Yermek (2004-04-22 20:53:00) [33]А можно такой вопрос:
Обязательно ли, если на ServerSocket ServerType=stThreadBlocking то и в ClientSocket обязательно должно быть NonBlocking.
Анонимщик (2004-04-22 15:30:00) [34]Во, за это спасибо, буду пытаться.
Digitman (2004-04-22 15:12:00) [35]при stThreadBlocking перевести гнездо в неблок.режим можно двумя способами :
1) в режим оконных нотификаций - вызовом WSAAsyncSelect, при этом придется "ручками" создать окно (ибо оно по умолчанию в stThreadBlocking не создается) и только после этого связать хэндл окна с хэндлом гнезда вышеупомянутой ф-цией
2) в режим событийных нотификаций - вызовом WSAEventSelect, при этом придется "ручками" создать объект Event и только после этого связать хэндл объекта Event с хэндлом гнезда вышеупомянутой ф-цией
далее, в зависимости от 1 или 2, в доп.потоке организуется либо цикл ожидания/выборки/диспетчеризации оконных сообщений либо цикл ожидания сигналов объекта Event
Digitman (2004-04-22 15:06:00) [36]stNonBlocking не создает доп.потоков, но создает единственное окно (для приема нотификаций от своих гнезд, ассоциированных с активными клиентами) и устанавливает режим асинхр.нотификации вызовом WSAAsyncSelect
stThreadBlocking не создает никаких окон, но создает для каждого активного соединения отдельный код.поток (т.н., транспортный поток), передавая этому потоку параметром новый объект-гнездо ClientSocket: TServerclientWinSocket, отражающий транспортный контекст соединения с данным активным клиентом и инициализированный по умолчанию для работы в блокирующем режиме
Polevi (2004-04-22 14:53:00) [37]>Анонимщик © (22.04.04 14:52) [9]
F1 WSAAsyncSelect
Анонимщик (2004-04-22 14:52:00) [38]А чем же тогда stThreadBlocking и stNonBlocking отличаются вообще?
Кроме того, каким образом эту асинхронность включить, извиняюсь на назойливость.
Digitman (2004-04-22 14:47:00) [39]
> обработка будет происходить только в одном потоке сервера
во-первых, никто не заставляет тебя в одном и том же потоке сервера выполнять именно обработкуданных, принимаемых последовательно от разных клиентов... в случае "тяжелой обработки" задача единственного потока сервера - чисто транспортная : быстро принятьданные из гнезда .. а уж обработкупринятых от конкр.клиента данных можно вынести в доп.поток, стартовав его тут же либо выбрав свободный на сей момент из пула доп.потоков, заранее созданных тобой после старта сервера
во-вторых, выбор режима stThreadBlocking отнюдь не означает, что ты не можешь в любой момент времени перевести гнездо в неблокирующий режим и включить для этого гнезда нужный механизм асинхронной нотификации (оконную или событийную - на твой вкус)
Анонимщик (2004-04-22 14:31:00) [40]Значит, я ошибался, когда считал, что, если выставить тип сервера в stThreadBlocking, то тогда отправка сообщений будет происходить без промедления (в смысле, функция якобы тут же отрабатывает).
Но если поставить nonBlocking, то тогда обработка будет происходить только в одном потоке сервера. Так? А это очень неудобно. Хотелось бы с каждым клиентом иметь свой поток.