Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > Чтение и запись в разных потоках


Автор: Sokolll 17.5.2007, 12:00
Использую IdTCPServer и IdTCPClient. Необходимо сделать, чтобы чтение и запись в сокет происходило в разных потоках и на клиенте и на сервере. Для этого на клиенте кидаю IdTCPClient  на форму - через него пишу. Создаю поток, в нем создаю еще один IdTCPClient - через него читаю.  Получается, что на сервере создаются два потока. Для того, чтобы можно было обратиться к потоку и через него писать пытаюсь использовать делаю  следующим образом: 
1)Соединяюсь с сервером из основоного потока клиентcкого приложения и из потока, через который собираюсь читать.
2) Из главного потока приложения отправляю серверу значение idTCPClient.Socket.Binding.ID  - IdTCPClient-a из читающего потока.
3) На сервере в OnConnect для того, чтобы определить, в каком потоке нужно писать, перебираю ID соединений всех потоков: TIdContext(IdTCPServer.Contexts.LockList.Items[i]).Connection.Socket.Binidng.ID    и  сраниваю с принятым  значением от клиента. 

Почему - то значение Binding.ID  всегда = 0. Объясните, пожалуйста,  как вообще работать со связками.
 Да и может быть лучше как-нибудь по-другому организовать чтение и запись в разных потоках.

Автор: MetalFan 18.5.2007, 08:38
может пересмотреть структуру приложения и осуществлять чтение и запись в одном потоке? либо передавать idTCPClient в вспомогательный поток, но тогда надо обеспечить потокобезобасность при работе с общими данными(в частности с idTCPClient).

Автор: Sokolll 18.5.2007, 14:11
У меня стоит задача - осуществить чтение и запись в разных потоках :(

Не подскажите, где можно найти какую-нибудь инфу по bindings. 
На клиенте делаю так:
Код


  begin
   SoCket.BoundIP:='localhost';
   Socket.BoundPort:=1050;
   SoCket.Binding.Bind;
   try
      Connect;
    except
      on E: Exception do
      begin
        ShowMessage('An Error occured while try to connect: '+E.Message);
        Exit;
      end;
    end;

 

Вылетает "Access violation". Подскажите, в чем ошибка?

Автор: MetalFan 18.5.2007, 22:59
а SoCket создан?

Автор: Sokolll 19.5.2007, 04:57
Как я понимаю, когда я создаю IDTCPClient, socket тоже создается, а клиент у меня создан:

IdTCPClient:=TIdTCPClient.Create;

Автор: aktuba 19.5.2007, 08:45
Цитата

Как я понимаю, когда я создаю IDTCPClient, socket тоже создается, а клиент у меня создан:

IdTCPClient:=TIdTCPClient.Create; 


Я чего-т не допонял... А какое отношение имеет SoCket к IdTCPClient?

Автор: Sokolll 19.5.2007, 09:05
Цитата

Я чего-т не допонял... А какое отношение имеет SoCket к IdTCPClient?


Socket - это IDTCPClient.Socket

Я просто код не весь вставил:
Код

IDTCPClient:=TIdTCPClient.Create;
 with IdTCPClient do
 begin
   SoCket.BoundIP:='localhost';
   Socket.BoundPort:=1050;
   SoCket.Binding.Bind;
   try
      Connect;
    except
      on E: Exception do
      begin
        ShowMessage('An Error occured while try to connect: '+E.Message);
        Exit;
      end;
    end;
 end;



Добавлено через 6 минут и 18 секунд
А еще такой вопрос: 

Создаю IdTCPServer, ставлю обработчик OnExecute, в котором ничего не делаю. Подсоединяется клиент и все начинает тормозит, в диспетчере задач мой сервер юзает 99% ресурсов процессора, хотя ни сервер, ни клиент никакой информации не пишет\не читает. 
В чем прична?

Автор: MetalFan 19.5.2007, 11:44
что за изврат?
чем не устроило:
Код

  idTCPClient.Host := '...';
  idTCPClient.Port := ...;
  idTCPClient.Connect;

p.s. хоть бы хелп посмотрел.
св-ва BoundIP/BoundPort - это "исходящие" параметры клиента. 
а Host и Port - к чему подсоединяться

Автор: Sokolll 19.5.2007, 16:46
Спасибо. 
Но как связывать то bindings?  ато  Access violation  и все...?

Автор: MetalFan 19.5.2007, 18:59
Sokolll, на кой тебе дались эти bindings???
указываешь порт, хост. делаешь коннект. что надо то еще?

Автор: Sokolll 20.5.2007, 19:42
Цитата

Sokolll, на кой тебе дались эти bindings???
указываешь порт, хост. делаешь коннект. что надо то еще?


Во-первых просто интересно, во-вторых, как писал, нужно организовать чтение и запись в разных потоках. А для того, чтобы определить на серере, в каком потоке надо писать, хотел использовать свойство bindings.ID, ведь как, я понимаю, его значение должно быть одинаковым и на клиенте и на сервере.

Так как с Bindings ничего не получилось, сделал так:
На клиенте сначала подключаюсь из читающего потока, затем из основного потока приложения.
При подключении на клиенте посылаю строку-идентификатор, состоящую из цифры 1 - для пишущего потока или цифры 2 - для читающего, и хэндла окна главной формы.
На сервере при подключении клиента читаю строку-идентификатор и присваиваю ее значению Connection.Tag.
Дальше проверяю, если 1-ый символ строки = '2' - значит это соединение с IdTCPCLient-ом чиатющего потока клиентского приложения - Exit;
Если '1' - значит это соедиенение с IdTCPClient-ом пишущего потока клиентсокого приложения и далее делаю следующее:
Надо определить в каком потоке писать (в потоке с Connection.Tag = '2......').
Перебираю Connection.Tag всех контекстов IdTCPServer-а   -  сравниваю Tag  cо строкой:  AContext.Connection.Tag только первый символ = '2'. При совпадении  в переменную типа Pointer присваиваю указатель на контекст.
Все. Теперь, если надо что-то послать на клиентское приложение, пишу в этом контексте.

Получилось замудренно, но работаетsmile







Автор: MetalFan 22.5.2007, 11:48
Цитата(Sokolll @  20.5.2007,  19:42 Найти цитируемый пост)
При подключении на клиенте посылаю строку-идентификатор, состоящую из цифры 1 - для пишущего потока или цифры 2 - для читающего, и хэндла окна главной формы.

не самая хорошая идея использовать для идентификации клиента в сети хэндл формы приложения...
уж лучше раздавать ID при подключении сервером

Автор: Sokolll 23.5.2007, 11:16
Цитата

уж лучше раздавать ID при подключении сервером


Спасибо, так и сделал. Получилось проще и лучше.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)