Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблемы при работе с Indy [D7, WinXP]


Страницы:   1 2 3 4 5 6 7 8

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.


Cyrax   (2006-10-18 12:45:00) [21]

Если ты причастен к его разработке, то ты всегда волен реализовать сервер так как тебе нужно.

Ну, предположим, так...
И какой из всего этого можно сделать вывод ?

з.ы. Видно, вы никогда не отправляли групповые TCP-пакеты...


Сергей М.   (2006-10-18 12:33:00) [22]

Да по барабану, на основе чего он там сейчас работает)
Если ты причастен к его разработке, то ты всегдаволен реализовать сервер так как тебе нужно.


Cyrax   (2006-10-18 12:11:00) [23]

Допустим, сервер работает на основе сторонних модулей (а не моего), не реализующих поддержку UDP...


Сергей М.   (2006-10-18 11:52:00) [24]


> сервер может не поддерживать UDP


Что мешает реализовать в нем такую поддержку ?


Cyrax   (2006-10-18 11:31:00) [25]

Так извращеннее всего...
Ну, модуль у меня TCP-шный, кроме того, сервер может не поддерживать UDP...


Сергей М.   (2006-10-18 11:25:00) [26]


> нужно максимально быстро найти сервер



> пользуясь только протоколом TCP/IP...


Это что, блажь ? Чем это обосновано ? Чем UDP помешал ?


Cyrax   (2006-10-18 11:20:00) [27]

Тут такая задача подвернулась. Надо извратиться и отправить широковещательный TCP-пакет для поиска сервера...
А вообще, нужно максимально быстро найти сервер (с неизвестным IP-адресом и неизвестным портом из известных диапазонов), пользуясь только протоколом TCP/IP...


Verg   (2006-10-17 09:49:00) [28]


> Отсоединяюсь я методом Disconnect (пробовал и DisconnectSocket).
>  При каждом очередном соединении клиента ОС выделяет ему
> новый порт. Если же задать порт клиента самому, то при повторном
> соединении возникает ошибка - порт то остался занятым...
>  
> С TIdTCPServer такой проблемы не возникает.
>
> Что самое интересное, пример работы с TIdTCPServer и TIdTCPClient
> (IdTCPDemo), скачанный с инета, показывает те же результаты.
>  
> На форумах читал, как обсуждали глюки некоторых компонентов
> Indy.
> Так вот, может это очередной глюк? Или отсоединяться (клиенту)
> нужно как то по-другому?


Это не от Indy.
см. http://book.itep.ru/4/44/tcp_443.htm
Состояние соединения TIME_WAIT.


Сергей М.   (2006-10-17 08:33:00) [29]


> Где в справке указано, что... Вообще, где в справке хоть
> что-то описано об этих уровнях


Не ту справку ты куришь.

Справка к индейским компонентам в основном ориентированы на батонокидателей, которые не заморачиваются низкоуровневым программированием гнезд.

Следует курить как минимум справку MS Windows Sockets 2 Reference (поставляется штатно), где сказано:

level = IPPROTO_TCP*

TCP_NODELAY BOOL Disables the Nagle algorithm for send coalescing.
* - included for backward compatibility with Windows Sockets 1.1  


BSD options not supported for setsockopt are:

...
TCP_NODELAY

The TCP_NODELAY option is specific to TCP/IP service providers. Enabling the TCP_NODELAY option disables the TCP Nagle Algorithm (and vice versa). The Nagle algorithm (described in RFC 896) is very effective in reducing the number of small packets sent by a host by essentially buffering send data if there is unacknowledged data already "in flight" or until a full-size packet can be sent ....

А еще лучше искать инф-цию в первоисточнике - MSDN.


> Везде одна и та же ошибка


В смысле "Access violation at address XXXXXXXX...." ?

И чему равен XXXXXXXX ? Входит ли XXXXXXXX в диапазон адресов, распределенных под образ твоегомодуля в ВАП процесса ?
Если входит, то в [117] - вранье, либо ты не умеешь пользоваться встроенным отладчиком.
Если не входит, то обязательновходит в диапазон адресов для образа какого-либо иного модуля, и эта инф-ция (т.е. какого конкретно модуля) не менее важна при поиске причин отказа.


Ketmar   (2006-10-16 23:35:00) [30]

>[126] Cyrax(c) 16-Oct-2006, 23:15
>Ну вот, самому ведь приходилось, а говоришь код пиши
>правильно, буфера не трогай...
я это делал "из спортивного интереса". в реальных задачах не приходилось ни разу.


Cyrax   (2006-10-16 23:15:00) [31]

Ketmar ©   (16.10.06 22:14) [125]
ну, я отключал.

Ну вот, самому ведь приходилось, а говоришь код пиши правильно, буфера не трогай... $\g

где-то на "королевстве" была статья...

паоищу.. Глядел какой-то форум по этой функции, но на C++ - на паскале не прокатывает...


Ketmar   (2006-10-16 22:14:00) [32]

>[124] Cyrax(c) 16-Oct-2006, 22:07
>Кто-нибудь отключал буферизацию TCP-пакетов с помощью
>SetSockOpt ?
ну, я отключал. только как -- убей, не помню. и вспоминать лениво. давно было. где-то на "королевстве" была статья по работе с сокетами, там в том числе и об этом сказано.


Cyrax   (2006-10-16 22:07:00) [33]

Ketmar ©   (15.10.06 23:19) [122]
жениться бы вам, барин... (ц)

Тогда останется один путь - повеситься...
Сейчас есть приоритеты и поважнее...

Сергей М. ©   (16.10.06 08:33) [123]
Кто такой Self в данном контексте ?

Ето наследник TIdTCPClient. Self я уже давно убрал. Он мне нужен был только чтоб добраться до SetSockOpt...

Нагель отключается на уровне  Id_IPPROTO_TCP.

И на уровне Id_IPPROTO_TCP отключал, и на уровне... в общем, все уровни перепробовал... Везде одна и та же ошибка...

Справку-то когда читать наконец научимся ?

Где в справке указано, что... Вообще, где в справке хоть что-то описано об этих уровнях. Например, всё, что написано про Id_IPPROTO_TCP:
Id_IPPROTO_TCP = IPPROTO_TCP;

Unit
IdStackConsts
Description
Id_IPPROTO_TCP

И так про все константы, используемые в SetSockOpt...

_________________________________________________________________
Кто-нибудь отключал буферизацию TCP-пакетов с помощью SetSockOpt ?


Сергей М.   (2006-10-16 08:33:00) [34]


> Cyrax ©   (15.10.06 19:15) [117]


> Self.Socket.Binding.SetSockOpt(Id_SOL_SOCKET, Id_TCP_NODELAY,
>  Char(@Id_SO_False), SizeOf(Id_SO_False));


Кто такой Self в данном контексте ?

Нагель отключается на уровне  Id_IPPROTO_TCP.
Справку-то когда читать наконец научимся ?


Ketmar   (2006-10-15 23:19:00) [35]

жениться бы вам, барин... (ц)


Cyrax   (2006-10-15 23:10:00) [36]

Задача никак не менялась.
Могу написать простейший автомат и реализовать его в своём модуле. Будет некоторая надстройка (реализованная только в моём модуле и не выходящая за его пределы) над прикладным протоколом (неизвестным в общем случае). Ещё подумаю...
Но это всё будет после того, как разберусь с текущим глюком с отключением буферизации... - это садомазо такое (похоже на ситуацию с языковой панелью, которую я всё-таки вытащил наружу)...


Ketmar   (2006-10-15 21:26:00) [37]

>[119] Cyrax(c) 15-Oct-2006, 20:09
>Если не поможет, буду отслеживать движение IP-пакетов и
>проводить всякие извращенские опыты...
ага. вместо чтобы написать простейший автомат... или по ходу обсуждения задача уже поменялась? лень перечитывать.


Cyrax   (2006-10-15 20:09:00) [38]

Ketmar ©   (15.10.06 19:39) [118]
вот же прикопался к буферизации...

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

чую, когда отключишь, будет пост типа "отключил. не помогло. что дальше?"

Если не поможет, буду отслеживать движение IP-пакетов и проводить всякие извращенские опыты...


Ketmar   (2006-10-15 19:39:00) [39]

вот же прикопался к буферизации. чую, когда отключишь, будет пост типа "отключил. не помогло. что дальше?" %-)


Cyrax   (2006-10-15 19:15:00) [40]

При вводе адреса в моей программе, где произошла ошибка, ничего не происходит, окно "CPU" не открывается. Но по этому адресу мне делать нечего...
При вводе адреса, к которому произошло обращение (00000068), окно "СPU" открывается. Меня смущает этот адрес - 00000068...

const Id_SO_True: boolean = true;
       Id_SO_False: boolean = false;
begin
Self.Socket.Binding.SetSockOpt(Id_SOL_SOCKET, Id_TCP_NODELAY, PChar(@Id_SO_False), SizeOf(Id_SO_False));

Ну так кто-нибудь отключал буферизацию или нет !?
Если да, то как...


Страницы:   1 2 3 4 5 6 7 8

Наверх

Титульная страница Поиск, карта сайта Написать письмо