![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблемы при работе с Indy [D7, WinXP]
Cyrax © (2006-08-26 18:46:00)Столкнулся я с такой проблемой. При использовании компонента TIdTCPClient при отсоединении от сервера не освобождается порт, занимаемый клиентом. Отсоединяюсь я методом Disconnect (пробовал и DisconnectSocket). При каждом очередном соединении клиента ОС выделяет ему новый порт. Если же задать порт клиента самому, то при повторном соединении возникает ошибка - порт то остался занятым...
С TIdTCPServer такой проблемы не возникает.
Что самое интересное, пример работы с TIdTCPServer и TIdTCPClient (IdTCPDemo), скачанный с инета, показывает те же результаты.
На форумах читал, как обсуждали глюки некоторых компонентов Indy.
Так вот, может это очередной глюк? Или отсоединяться (клиенту) нужно как то по-другому?
Правильно ли я понимаю механизм соединения клиента с сервером:
При попытке клиента соединиться с сервером (метод TIdPeerThread.Run на клиенте) на стороне сервера вначале создаётся поток для обслуживания этого клиента. Далее происходит попытка установления связи с клиентом. Событие OnExecute на сервере генерится именно после создания потока. При этом возможна ситуация, когда поток создан, а соединение не установлено. При последующем успешном соединении этого же клиента используется тот же поток.
Если я в чём-то ошибаюсь, прошу меня поправить.
Остаётся непонятно, почему в начале обработчика события OnExecute нужно ставить проверку "if not AThread.Terminated". Что, OnExecute генерится ещё и при завершении работы потока?
Есть у меня и другая проблема. При создании объекта TIdTCPServer присвоил полям OnConnect и OnDisconnect имена обработчиков. Напомню, что я пишу модуль, и никакого интерфейса, а тем более визуальных компонентов, нет. Т.е. все объекты я создаю и инициализирую сам... Так вот, в процессе соединения и отсоединения клиентов сервер генерирует события OnConnect и OnDisconnect соответственно и вызывает мои обработчики этих событий (по крайней мере, должен). С коннектом проблем нет. НО: событие OnDisconnect на сервере не генерируется при отсоединении клиента. Это событие генерируется только при завершении работы сервера (IdTCPServer.Active := false). Как я понял из help'а, оно должно генерироваться при каждом отсоединении клиента. Именно так и происходит в случае с сервером и клиентом, созданных визуально путём установки на форму компонентов (в этом случае все необходимые поля инициализируются нужным образом).
Может я не все нужные поля у IdTCPServer проинициализировал?
Вот моя инициализация клиента:
MaxLineLength := DataMax;
MaxLineAction := maException;
ReadTimeout := 0;
BoundPort := 0; // чтобы не возникало проблем с занятым портом
Host := '127.0.0.1'; // пока для проверки
Port := 6002;
Инициализация сервера:
DefaultPort := port;
ThreadMgr := TIdThreadMgrDefault.Create(id_component);
MaxConnections := ClientsMax;
ListenQueue := 15;
OnExecute := onexecute;
OnConnect := onconnect; // мой обработчик
OnDisconnect := ondisconnect; // мой обработчик
_______________________
Дополнительные вопросы:
1. Как в винде посмотреть, какие порты в данный момент заняты и какими прогами (средствами винды, без программирования) + как принудительно освободить занятый порт (естественно, с завершением работы проги).
2. Свойство BoundIP клиента указывает IP компа, на котором можно его запускать ?
_______________________
Напоследок хочу узнать мнение тех, кто работал с Indy. Я пишу модуль, который будет обеспечивать связь клиентов с сервером по TCP/IP. Интерфейс представлен 4-мя функциями: инициализация, отправка, получение и завершение. Так вот, целесообразно ли использовать Indy для этих целей. Или проще напрямую работать с winsock, ведь Indy тоже работат через winsock.
Сергей М. (2006-08-28 16:28:00) [141]
> Cyrax © (28.08.06 16:16) [15]
>
>
Не надо месить в одну кучу сервера и клиента.
Либо ты о сервере, либо о клиенте.
Ты о ком ?
Cyrax (2006-08-28 16:16:00) [142]
Сергей М. © (28.08.06 15:40)
Хорошо, гляну в исходники...
Но следующие вопросы остаются открытыми:
1. При отсоединении клиента (disconnect, либо disconnectsocket) порт не освобождается (см. Cyrax © (28.08.06 13:03)).
2. Серверные OnDisconnect'ы не вызываются при отсоединении клиентов (только при завершении работы проги / деактивации сервера).
Сергей М. (2006-08-28 15:40:00) [143]
> Что значит "циклически" ?
Циклически означает "в цикле".
ты в состоянии заглянуть в исх-ки сервера и проанализировать их ?
> как насчёт дективации сервера ?
А что насчет нее ?
Серверный диспетчер при поступлении "команды" Active := False командует всем работающим своим потокам "Terminate" и ждет пока всесозданные им потоки завершатся.
Cyrax (2006-08-28 15:15:00) [144]Что значит "циклически" ? В какие моменты времени ?
И как насчёт дективации сервера ?
Сергей М. (2006-08-28 13:19:00) [145]
> Циклически после успешного соединения - я так понимаю, генерируется
> однократно после каждого успешного соединения (в рамках
> потока).
Нет, не правильно.
После успешного установления соединения создается новый экз-р TIdPeerThread (или берется уже готовый, ранее созданный и ждущий своего использования в пуле тредпул-менеджера), в контексте которого с этого момента циклически вызывается обработчик OnExecute вплоть до самой "смерти" соединения.
Cyrax (2006-08-28 13:03:00) [146]Наконец-то появились нормальные ответы...
[i]
> Slym © (28.08.06 06:53)
[/i]
Прибиндивать сокет клиента - не моя идея, это требование организации (возможность указания порта клиента).
Звучит, конечно, навязчиво... Но всё-таки: когда указываем порт клиента, то при повторном соединении возникает ошибка привязки сокета (без завершения работы проги - соединились, отсоединились, соединились => error). Напрашивается на то, что при отсоединении порт не освобождается... Возможно, отсоединяюсь не так как нужно (см. Cyrax © (26.08.06 18:46)). Здесь уже надо знать Indy...
[i]
> Сергей М. © (28.08.06 08:35)
[/i]
Циклически после успешного соединения - я так понимаю, генерируется однократно после каждого успешного соединения (в рамках потока).
+ генерируется при завершении потока (после деактивации сервера)?
Как, всё-таки быть с генерацией события OnDisconnect на сервере ? (см. Cyrax © (26.08.06 18:46)). Когда это событие должно генерироваться - при отсоединении каждого из клиентов или при завершении работы сервера (при деактивации сервера) ?
Сергей М. (2006-08-28 08:35:00) [147]
> Cyrax © (26.08.06 18:46)
Событие TIdTCPServer.OnExecute возбуждается циклически(а не однократно !) в контексте соответствующего потока TIdPeerThread после успешногоустановления соединения с клиентом.
Проверка флага Terminated нужна для оперативного реагирования на команду деактивации сервера (IdTCPServer.Active := False).
Slym (2006-08-28 06:53:00) [148]Клиент вообще не должен думать о своем порте, ему хватает сведений о порте сервера. Порт клиента система сама выделит свободный порт из разрешенного диапазона (>1024)
И зачем прибиндивать клиентский сокет?
при завершении проги, все Хендлы обнуляются, а нулевые освобождаются...
Cyrax (2006-08-28 00:11:00) [149]Dmitrij_K, может всё-таки скажешь, в чём я ошибаюсь по поводу механизма...
Cyrax (2006-08-28 00:09:00) [150]кто это кому и что должен?
Уточню формулировку: "При очередном соединении клиента ему выделяется порт с номером... Короче, ясно ведь, что имеется ввиду! Замечу: при условии, что другие проги за это время не занимали и не освобождали портов...
...если не устраивает логика работы...
О какой логике работы идёт речь?
Пока прозвучала только моя версия, которая подтверждается практически. Она меня вполне устраивает... Вопрос в другом - освобождается ли порт?
Насчёт предположений.
Обращаюсь всё-таки к тем, кто знает. Пусть порпавят, если ошибаюсь...
А лезть для этого в исходники - изврат...
Кто нибудь скажет, почему ошибка то возникает !!! (моё предыд. сообщение). Тогда и "споры ни о чём" разрешатся...
Dmitrij_K (2006-08-27 23:27:00) [151]
> А как насчёт стандартных средств винды (например, брандмауэр
> Windows).
В win нет стандартных средств, Outpost FireWall имхо самый инф
ормативный из тех что я видел
> Или таких ситуаций быть не пожет (при завершении проги порт в любом случае будет освобождён виндой?
имхо так
Ketmar (2006-08-27 22:34:00) [152]> [3] Cyrax © (27.08.06 22:26)
> при очередном соединении клиента ему должен быть выделен
> тот же порт, что и при предыдущем
кто это кому и что должен? можно пошерстить winsock, если не устраивает логика работы. или своё написать. лично я исходников winsock не видел, и предоположения не делаю. в силу чайниковости, наверное.
Cyrax (2006-08-27 22:30:00) [153]По поводу механизма соединения клиента и сервера.
Прошу меня поправить, если невломы писать...
Cyrax (2006-08-27 22:26:00) [154]Что порт при очередном соединении не обязательно должен быть тем же самым, я согласен. Но не думаю, что винда будет выделять произвольный порт (из свободных). Наиболее вероятный алгоритм - выделение первого свободного (из определённого диапазона). Если это так, то при очередном соединении клиента ему должен быть выделен тот же порт, что и при предыдущем (если за время между соединениями никакие другие проги не занимали порты).
В подтверждение повторю вопрос, заданный в первом сообщении:
Почему при повторном соединении клиента генерится ошибка, связанная с binding'ом сокета? (это в том случае, когда мы прямо укзываем в клиенте порт привязки)
Файрволом например Outpost FireWall
А как насчёт стандартных средств винды (например, брандмауэр Windows).
> Завершить работу проги
Остроумно. Но я имел ввиду ситуацию, когда прога, которой был выделен порт, при завершении его не освобождает по каким-либо причинам (например, прога глючная). Или таких ситуаций быть не пожет (при завершении проги порт в любом случае будет освобождён виндой) ?
такие вопросы задаются в форуме сети
Вопросы об освобождении портов и механизме соединения клиента с сервером - да. Но о генерации событий OnExecute и OnDisconnect всё-таки в компонентах...
Dmitrij_K (2006-08-26 21:03:00) [155]PS такие вопросы задаются в форуме сети
Dmitrij_K (2006-08-26 21:02:00) [156]Отвечу на то что могу
Клиенту выдается свободный порт, и необязательно он будет такой же как в прошлый раз (мне всегда так казалось Ж))
Механизм ты понял неправильно.
> Как в винде посмотреть, какие порты в данный момент заняты
> и какими прогами (средствами винды, без программирования)
Файрволом например Outpost FireWall
> как принудительно освободить занятый порт (естественно,
> с завершением работы проги).
Завершить работу проги
> Или проще напрямую работать с winsock,
Зависит от твоих знаний