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.


Сергей М.   (2006-09-05 11:23:00) [101]


> по-другому не получится.


Чтой-то вдруг ?


Cyrax   (2006-09-05 10:12:00) [102]

Согласен, но по-другому не получится...


Сергей М.   (2006-09-05 10:06:00) [103]


> Нужно, чтобы эти функции сразу же возвращали результат (код
> ошибки), а для этого нужно подождать, пока выполниться операция
> чтения/записи в соответствующем потоке


При этом теряется весь смысл выполнения трансп.операций в доп.потоке.


> Остановился пока на варианте ждать в цикле, пока не завершится
> операция в потоке


Плохой вариант.


Cyrax   (2006-09-05 09:37:00) [104]

Всё, запарился... Не буду извращаться с Indy...
Сделаю в соответствии с идеологией Indy - все read/write в OnExecute и потоки в OnExecute. А то OnDisconnect достал...

Попутно соображаю по поводу того, как лучше организовать implement моих фунций чтения/записи. Нужно, чтобы эти функции сразу же возвращали результат (код ошибки), а для этого нужно подождать, пока выполниться операция чтения/записи в соответствующем потоке.
Остановился пока на варианте ждать в цикле, пока не завершится операция в потоке (с помощью флагов), а затем результат операции возвращать в главную программу...

Что касается порта клиента, то проверил OutPost'ом - порт все-таки освобождается... но ошибка выходит... Может, руки кривые...
Проверю ещё раз, где именно вылазит.


Сергей М.   (2006-09-04 11:52:00) [105]


> Cyrax ©   (04.09.06 11:49) [51]


Возьми любую готовую утилитку  (а-ля TCPView) да посмотри, занят ли порт 55559 после первого же дисконнекта клиента.


Cyrax   (2006-09-04 11:49:00) [106]

Глюко всяко случается...


Сергей М.   (2006-09-04 11:47:00) [107]


> ты пробовал создать файлы с текстом из [32] и скомпилить
> ?
>


А нафига ?
Если ты утверждаешь, что именно строка IdTCPClient1.Connectприводит к отказу 10048, то сервер тут вообще ни при чем .. Зачем, спрашивается его компилить ?)


Cyrax   (2006-09-04 11:42:00) [108]

Что за полтергейст... средь бела дня...

А ты пробовал создать файлы с текстом из [32] и скомпилить ?

P.S. Знаю, страшно ломает...


Сергей М.   (2006-09-04 11:35:00) [109]


> Cyrax ©   (04.09.06 11:28) [47]


Повторил твой код с максимальной точностью

 object IdTCPClient1: TIdTCPClient
   ...
  BoundPort = 55559
  Host = '127.0.0.1'
  ...
end

Никаких "Address already in use" по-прежнему не наблюдаю, хоть без хоть с перезагрузкой клиента.


Cyrax   (2006-09-04 11:28:00) [110]


Socket Error # 10048
Address already in use.

Даже после перезагрузки клиента и сервера при соединении клиента сразу же возникает это исключение (с тем же портом клиента)...


Сергей М.   (2006-09-04 11:21:00) [111]


> я обрабатываю это исключение в обработчике OnDisconnect.
>  А OnDisconnect у меня вызывается стандартным обработчиком
> этого исключения, даже если не отлавливать try...except'ом


Ну можно и так.


> мой пример, где как раз и использую твой код


Приведи дословно текст сообщения об исключении, возникающем при выполнении IdTCPClient1.Connect


Cyrax   (2006-09-04 11:08:00) [112]

Если возникло исключение, то оно будет при этом перехвачено и обработано тобой должным образом.
При чем здесь OnDisconnect ?

Хочу сказать? что я обрабатываю это исключение в обработчике OnDisconnect. А OnDisconnect у меня вызывается стандартным обработчиком этого исключения, даже если не отлавливать try...except'ом...

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

> Как насчёт [32]?

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


Сергей М.   (2006-09-04 10:50:00) [113]


> Cyrax ©   (04.09.06 10:37) [43]


Ты ведь спросил, как оперативно отреагировать на отключение клиента в момент выполнения операций приема/передачи, я тебе и ответил - заключать вызов таких ф-ций в try..except

Если возникло исключение, то оно будет при этом перехвачено и обработано тобой должным образом.

При чем здесь OnDisconnect ?


> Как насчёт [32]?


А что насчет него ?
Я тебе уже сказал - нет никакой необходимости знать сколько байт доступно во входном потоке.
Сколько требуется прочитать в соответствии с твоим прикладным протоколом инф.обмена, столько и читай.


Cyrax   (2006-09-04 10:37:00) [114]

По поводу [23]:
Обработчик OnDisconnect вызывается стандартным обработчиком исключения (см. [31])... (по крайней мере, у меня так работало, без своих except'ов).

> см. [21]

Как насчёт [32]?


Сергей М.   (2006-09-04 10:30:00) [115]


> мне нужно обнаружить отсоединение клиента как можно раньше,
>  хотя бы в момент чтения/записи


см. [23]


> как насчёт освобождения порта ?


см. [21]


Cyrax   (2006-09-04 10:27:00) [116]

Сергей М. ©   (04.09.06 10:14) [39]

Вообще-то примерчик неплох... стоит попробовать.

А как насчёт освобождения порта ?


Сергей М.   (2006-09-04 10:14:00) [117]

with AThread do
while not Terminated and Connection.Connected and GetDataToSend(SomeDataToSend, SomeTimeout) do begin
 try
   Connection.SomeWriteMethod( ..SomeDataToSend ... );
 except
   Connection.Disconnect;
 end;
end;


Cyrax   (2006-09-04 10:14:00) [118]

Ну и делай)

Ну а варианты то какие ?  Например, с OnExecute.

в чем проблема-то

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


Сергей М.   (2006-09-04 10:07:00) [119]


> мне нужно это делать именно по запросу главной программы


Ну и делай) ... в чем проблема-то ? не знаешь как синхронизировать потоки или что ?


Cyrax   (2006-09-04 10:05:00) [120]

Чё то ничего не понял... трудно соображать поутру... наверное, от Ketmar'а пошло...

Если я буду передавать данные в OnExecute, то ... да мне нужно это делать именно по запросу главной программы...


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

Наверх

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