Форум: "Сети";
Текущий архив: 2003.07.10;
Скачать: [xml.tar.bz2];
ВнизМожно ли заставить TIdTCPConnection сообщать о приходе данных? Найти похожие ветки
← →
Zelius (2003-04-29 17:28) [0]На серверной стороне использую TidTcpServer, на клиенте TidTcpClient, хочу по одному каналау передавать данные как по инициативе клиента, так и сервера. Процедура оброботки TidTcpServer.OnExecute:
with aThread as TEPingConnThread do
begin
while NOT Terminated do
begin
HandleQueue; // отработать очередь данных на отсылку клиенту
if aThread.Connection.IOHandler.Readable(0) then HandleInput; // принять входящие данные
FEvent.WaitFor(500);
end;
end;
Мне не нравится интервал ожидания 500 мс, хочу от этого избавиться, но не знаю как это сделать с помощью Indy.
← →
$hade (2003-04-30 09:03) [1]>Мне не нравится интервал ожидания 500 мс
А зачем ты тогда вставил FEvent.WaitFor(500)?
И кто такой TEPingConnThread,FEvent?
← →
Zelius (2003-04-30 13:09) [2]Я его вставил, что бы этот поток не загружал процессор постоянным исполнением.
TEPingConnThread - это наследник TidPeerThread.
← →
Reindeer Moss Eater (2003-04-30 14:03) [3]Никакого "постоянного выполнения" и так не будет.
OnExecute генерится только когда, когда есть что обрабатывать
← →
$hade (2003-04-30 14:06) [4]а с чего он его грузить будет??
делай в первой строке OnExecute
readbuffer(b,sizeof(b)); - тут будет сидеть до тех пор пока не получит sizeof(b) байт от клиента или до TimeOut"а...
handleInput;
>TEPingConnThread - это наследник TidPeerThread
и что он делает у тебя?
Приведи побольше кода...понятней будет что ты хочеь сделать...
← →
$hade (2003-04-30 14:11) [5]2Reindeer Moss Eater
на самом деле оно генерится не только когда есть что обрабатывать...
например когда у КЛИЕНТА ты вызываешь Read(...
когда клиент только что подключился - сразу же после обработки
OnConnect...и не факт что в этот момент есть что читать ОТ клиента...
← →
Zelius (2003-04-30 14:54) [6]$hade © (30.04.03 14:06)
Дело в том, что я не могу блокировать поток отвечающий за прием данных, так как через него же хочу отправлять данные в произвольный момент, то есть на сервере произошло событие и мне надо об этом уведомить клиента, это может произойти в тот момент, когда поток будет висеть и ждать входящих данных.
А работаю я с потомком TidPeerThread для удобства, так как храню в нем данные необходимые для работы с каждым соединением.
← →
Zelius (2003-04-30 14:55) [7]
> Reindeer Moss Eater (30.04.03 14:03)
> Никакого "постоянного выполнения" и так не будет.
> OnExecute генерится только когда, когда есть что обрабатывать
Вы не правы, рекомендую посмотреть исходники Indy
← →
$hade (2003-04-30 15:22) [8]блин! а что тебе мешает сделать так:
var // глобальные переменные
Th:IdPeerThread;
...
OnConnect(AThread:TIdPeerThread);
begin
Th:=AThread;
end;
OnExecute(AThread...
begin
AThred.connectiom.read... то есть тут происходит ТОЛЬКО чтение от клиента....
end;
и все.... далее в ЛЮБОМ месте (когда тебе надо отправить клиенту данные)
Th.Connection.writebuffer например...
Не согласен??
ps:естественно тут только общее описание...конкретно - для одного клиента...а для нескольких клиентов - посложнее будет...там много нюансов...
Я делал реальный проект - оно работает...
Ежели что - пиши на мыло...
← →
$hade (2003-04-30 15:25) [9]есть такая штука - TThreadList..подумай над этим на досуге...;-)
← →
Zelius (2003-04-30 15:33) [10]
> $hade © (30.04.03 15:22)
Ты хочешь сказать, что можно одновременно из разных потоков по одному сокету принимать и посылать данные?
← →
Reindeer Moss Eater (2003-04-30 15:41) [11]на самом деле оно генерится не только когда есть что обрабатывать...
например когда у КЛИЕНТА ты вызываешь Read(...
когда клиент только что подключился - сразу же после обработки
OnConnect...и не факт что в этот момент есть что читать ОТ клиента...
Про ЧТЕНИЕ от клиента я не упоминал.
OnExecute генерится только когда, когда есть что обрабатывать
И отдавать тики процессора другим нитям в этом обработчике нет никакой необходимости. Это то что я хотел сказать.
← →
Reindeer Moss Eater (2003-04-30 15:48) [12]Исходный вопрос:
Можно ли заставить TIdTCPConnection сообщать о приходе данных?
Ответ:
Заставлять не надо. Будет сгенерено событие OnExecute, которое и сигнализирует, что данные есть.
← →
Reindeer Moss Eater (2003-04-30 15:49) [13]Или что пора вызывать синхроныый метод чтения данных
← →
Zelius (2003-04-30 15:57) [14]
> Reindeer Moss Eater (30.04.03 15:48)
Насколько я понял - OnExecute генерируется при установлении соединения, а не при приходе данных.
← →
Reindeer Moss Eater (2003-04-30 15:59) [15]А OnConnect когда по твоему генериться?
← →
Reindeer Moss Eater (2003-04-30 16:06) [16]А работаю я с потомком TidPeerThread для удобства, так как храню в нем данные необходимые для работы с каждым соединением.
Излишество это.
Есть TidPeerThread.Data в котором можно хранить ссылку на любые свои данные.
← →
Zelius (2003-04-30 16:14) [17]
> Reindeer Moss Eater (30.04.03 15:59)
> А OnConnect когда по твоему генериться?
Из DoConnect, который в свою очередь из BeforeRun.
Я посмотрел исходники - OnExecute вызывается не при появлении данных, а постоянно, пока соединение не закрыто и когда OnExecute возвращает управление! Что бы дождаться данных все равно надо вызывать ф-ию чтения и блокировать поток.
← →
Zelius (2003-04-30 16:16) [18]
> Reindeer Moss Eater (30.04.03 16:06)
> А работаю я с потомком TidPeerThread для удобства, так как
> храню в нем данные необходимые для работы с каждым соединением.
>
> Излишество это.
> Есть TidPeerThread.Data в котором можно хранить ссылку на
> любые свои данные.
Прошу прощения, не только данные, я там еще несколько методов реализовал. Согласен, что тоже самое можно сделать разными способами, просто мне хотелось попробовать такой метод.
← →
Reindeer Moss Eater (2003-04-30 16:23) [19]Я посмотрел исходники - OnExecute вызывается не при появлении данных, а постоянно, пока соединение не закрыто и когда OnExecute возвращает управление! Что бы дождаться данных все равно надо вызывать ф-ию чтения и блокировать поток.
Reindeer Moss Eater (30.04.03 15:49)
Или что пора вызывать синхроныый метод чтения данных
Объясни тупому: блокировать-то зачем???
← →
Reindeer Moss Eater (2003-04-30 16:25) [20]В OnExecute надо либо читать, либо писать. Зачем блокировать нитку PeerThread????
← →
Zelius (2003-04-30 16:40) [21]
> Reindeer Moss Eater (30.04.03 16:23)
Именно вызов синхронного метода чтения (а в инди других нет) и приводит к блокированию потока! Чего я и хочу избежать! Я не специально блокирую поток, а наоборот пытаюсь этого избежать :)
← →
$hade (2003-04-30 16:50) [22]>Ты хочешь сказать, что можно одновременно из разных потоков по одному сокету принимать и посылать данные?
Почему из разных то?? это один и тот же поток....
создавать Th не надо...просто присваеваешь....
Вощщем примерно так это выглядит у меня...
procedure TSrvCore.TCPSrvConnect(AThread: TIdPeerThread);
var
NewClient: PClient;
begin
try
with ActiveClients.LockList do
begin
GetMem(NewClient, SizeOf(TClient));
NewClient.DNS := AThread.Connection.Socket.Binding.PeerIP + ":"
+ IntToStr(AThread.Connection.Socket.Binding.PeerPort);
NewClient.UserName := "Guest";
NewClient.WorkDir := "";
NewClient.ConnecttionID := ConnID;
NewClient.Autorized := false;
NewClient.AutorizeAttempt := 0;
NewClient.SoftwareVersion := 0;
NewClient.ConnectionTime := now;
NewClient.WorkState := 1;
NewClient.RecivedFiles := 0;
NewClient.RecivedBytes := 0;
NewClient.SendFiles := 0;
NewClient.SendBytes := 0;
NewClient.UserUID := random($FFFFF);
NewClient.Thread := AThread;
AThread.Data := TObject(NewClient);
Add(NewClient);
AT := Count;
end;
finally
ActiveClients.UnlockList;
end;
AThread.Connection.ReadTimeout := SrvSettings.Timeout;
AThread.Connection.Intercept:=CryptIntrecept;
AThread.Connection.OnWork := OnWork;
UpdateLV(usAddUser, NewClient);
end;
..............
ActiveClients:TThreadList; - лист потоков активных соединений...:-)
NewClient:PClient - указатель на структуру TClient - просто рекорд с данными о клиенте...
AThread.Data := TObject(NewClient); - после этого из любго события (execute,disconnect) я могу сделать
Cli:=PClient(AThread.Data) и в cli у меня будет вся инфа о подключенном клиенте...
NewClient.Thread := AThread; - с точностью до наоборот! т.е. из
любого места программы выбираем из ActiveClients (обычный TList,список только заточеный под многопоточность) item - и это будет ссылка на NewClient а там соответственно на AThread...
Например: Отправляем данные всем клиентам
with ActiveClients.LockList do
try
for i:=0 to Count-1 do
begin
Cli:=PClient(Items[i]);
TIdPeerThread(.cli.thread).Connection.Write("FuckOff");
TIdPeerThread(.cli.thread).Connection.Disconnect;
end;
finally
ActiveClients.UnLockList;
end;
Сильно запутанно...сорри...торопился...:-)
← →
Reindeer Moss Eater (2003-04-30 16:50) [23]... и приводит к блокированию потока! Чего я и хочу избежать!
И что тебе это даст?
← →
Reindeer Moss Eater (2003-04-30 16:59) [24]Дело конечно хозяйское, но TCP сервера работают примерно по такой схеме:
1. Дождаться запроса услуги от клиента
2. Выполнить запрос клиента, и отправить ему результат
3. Перейти к пункту 1.
← →
$hade (2003-04-30 17:03) [25]2Reindeer Moss Eater
вполне согласен,но все же иногда надо что либо послать клиенту без его запроса...к примеру сообщение от админа сервера....в то время когда клиент заливает 50Mb файл на сервер...:-)
← →
Zelius (2003-04-30 17:04) [26]
> $hade © (30.04.03 16:50)
Я все понял кроме одного - можно ли параллельно с одного и того же сокета посылать и принимать данные, причем из разных потоков??? К сожалени, никак не могу найти статью на эту тему! Придется похоже руками пробовать...
По поводу кода, вместо ActiveClients я пользуюсь TcpServer.ThreadList, а вместо TClient я храню как раз данные в TMyidPeerThread, что вобщем одно и тоже.
← →
Zelius (2003-04-30 17:08) [27]
> Reindeer Moss Eater (30.04.03 16:59)
А иногда им еще надо передавать произвольные данные! Например аська! Сервер не только получает сообщения от клиента, но и передает их ему, когда те появляются!
← →
$hade (2003-04-30 17:18) [28]>можно ли параллельно с одного и того же сокета посылать и принимать данные, причем из разных потоков???
а зачем?? зачем из разных то?? ты сохраняешь указатель на поток...и можеш обращаться к ЭТОМУ ЖЕ ПОТОКУ из любого места через указатель...
← →
Zelius (2003-04-30 17:34) [29]
> $hade © (30.04.03 17:18)
Конечно могу, но это не значит что посылка данных будет выполнена в контексте этого потока. В контексте потока код будет выполнен только тогда, когда он будет вызван из обработчика OnExecute. Или я что-то не понимаю...
← →
Bug (2003-04-30 17:36) [30]$hade © (30.04.03 17:18)
>>а зачем?? зачем из разных то?? ты сохраняешь указатель на
>>поток...и можеш обращаться к ЭТОМУ ЖЕ ПОТОКУ из любого места
>>через указатель...
ты уверен?
← →
$hade (2003-04-30 17:46) [31]2Bug
а ты нет? объясни...:-)
p:pointer;
AThread:TIdPeerThread;
p:=TObject(AThread);
...
TIdPeerThread(p).Connection.write <-> AThread.Connection.write
Это разные потоки??
← →
Zelius (2003-04-30 17:51) [32]
> $hade © (30.04.03 17:46)
> 2Bug
> а ты нет? объясни...:-)
>
> p:pointer;
> AThread:TIdPeerThread;
>
> p:=TObject(AThread);
> ...
> TIdPeerThread(p).Connection.write <-> AThread.Connection.write
>
> Это разные потоки??
Это разные потоки.
← →
Zelius (2003-04-30 17:53) [33]
> $hade © (30.04.03 17:46)
Сорри, поторопился! Нет, конечно это один и тот же объект, но посылая данные так как ты указал, ты посылаешь их в контексте скорее всего главного потока!
← →
$hade (2003-04-30 17:54) [34]С чего бы это??
← →
Zelius (2003-04-30 18:00) [35]
> $hade © (30.04.03 17:54)
Потому что для того что бы воспользоваться контекстом потока TidPeerThread необходимо вставлять код в OnExecute. Ты проверь! Поставь бряк внутри OnExecute, посмотри в View \ Debug Windows \ Threads ID потока, а потом поставь бряк на твою отсылку данных и повтори тоже самое. Мне кажется, что это буду разные потоки.
← →
$hade (2003-04-30 18:14) [36]$hade © (30.04.03 17:54)
С чего бы это??
Это относилось к
>Это разные потоки.
Просто мы вместе пишем...:-)
А по поводу
>Zelius © (30.04.03 18:00)
...да...возможно это разные потоки...то есть вызов write во втором случае идет из основного потока...
Это работает...правильно работает...тока пока я не могу объяснить...:-)))
(за 12 часов сидения за компом уже плохо соображаю...:-((...
часа через 2 вылезу...пообчаемся на эту тему дальше...пошел пиво пить....
← →
Zelius (2003-04-30 19:11) [37]
> $hade © (30.04.03 18:14)
Конечно это будет работать, только вот многопоточности не будет, будут чувствоваться тормоза при больших пересылках ( а если еще и через интернет, то и подавно), и потом, есть шанс, что связь оборвется в момент когда ты захочешь что-нибудь послать, в этом случае есть шанс получить ошибку что-то типа Access Violation.
Однако вопрос открыт!
Что-то мне не очень нравится Инди :( Вроде все идет нормально, а потом мелкая пакасть с ее стороны губит самые хорошие идеи! :( Останавливает только то, что не хочется тратить время на реализацию интернет протоколов...
← →
Reindeer Moss Eater (2003-04-30 20:11) [38]Zelius © (30.04.03 17:08)
> Reindeer Moss Eater (30.04.03 16:59)
А иногда им еще надо передавать произвольные данные! Например аська! Сервер не только получает сообщения от клиента, но и передает их ему, когда те появляются!
Я тебе про сервер, а ты мне про клиента не рассказываешь.
← →
Reindeer Moss Eater (2003-04-30 20:15) [39]Я все понял кроме одного - можно ли параллельно с одного и того же сокета посылать и принимать данные, причем из разных потоков??? К сожалени, никак не могу найти статью на эту тему! Придется похоже руками пробовать...
По поводу кода, вместо ActiveClients я пользуюсь TcpServer.ThreadList, а вместо TClient я храню как раз данные в TMyidPeerThread, что вобщем одно и тоже.
Можно!
Пиши один обработчик OnExecute и подключись сотней клиентов. Все соединения будут обрабатываться одновременно (насколько это вообще правомочно утверждать для однопроцессорной Windows машины)
← →
Reindeer Moss Eater (2003-04-30 20:20) [40]$hade © (30.04.03 17:03)
2Reindeer Moss Eater
вполне согласен,но все же иногда надо что либо послать клиенту без его запроса...к примеру сообщение от админа сервера....в то время когда клиент заливает 50Mb файл на сервер...:-)
Все правильно. Нужно иногда посылать сообщения от админа клиенту.
Только это не означает, что делать это надо с помощью того же самого TCP соединения, по которому качается файл размером 50 м.
Делается это в дополнительном соединении, работающем по точно такой же схеме.
Страницы: 1 2 вся ветка
Форум: "Сети";
Текущий архив: 2003.07.10;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.036 c