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

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

Можно ли заставить TIdTCPConnection сообщать о приходе данных? [D7, Win2k]


Страницы:   1 2 3 4

Zelius ©   (2003-04-29 17:28:00) 

На серверной стороне использую 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.


Инди   (2003-04-30 20:45:00) [21]

Удалено модератором
Примечание: Не по делу можно в "Потрепаться"


Reindeer Moss Eater   (2003-04-30 20:20:00) [22]

$hade © (30.04.03 17:03)
2Reindeer Moss Eater
вполне согласен,но все же иногда надо что либо послать клиенту без его запроса...к примеру сообщение от админа сервера....в то время когда клиент заливает 50Mb файл на сервер...:-)


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


Reindeer Moss Eater   (2003-04-30 20:15:00) [23]

Я все понял кроме одного - можно ли параллельно с одного и того же сокета посылать и принимать данные, причем из разных потоков??? К сожалени, никак не могу найти статью на эту тему! Придется похоже руками пробовать...
По поводу кода, вместо ActiveClients я пользуюсь TcpServer.ThreadList, а вместо TClient я храню как раз данные в TMyidPeerThread, что вобщем одно и тоже.


Можно!
Пиши один обработчик OnExecute и подключись сотней клиентов. Все соединения будут обрабатываться одновременно (насколько это вообще правомочно утверждать для однопроцессорной Windows машины)


Reindeer Moss Eater   (2003-04-30 20:11:00) [24]

Zelius © (30.04.03 17:08)

> Reindeer Moss Eater (30.04.03 16:59)

А иногда им еще надо передавать произвольные данные! Например аська! Сервер не только получает сообщения от клиента, но и передает их ему, когда те появляются!

Я тебе про сервер, а ты мне про клиента не рассказываешь.


Zelius   (2003-04-30 19:11:00) [25]


> $hade © (30.04.03 18:14)

Конечно это будет работать, только вот многопоточности не будет, будут чувствоваться тормоза при больших пересылках ( а если еще и через интернет, то и подавно), и потом, есть шанс, что связь оборвется в момент когда ты захочешь что-нибудь послать, в этом случае есть шанс получить ошибку что-то типа Access Violation.

Однако вопрос открыт!
Что-то мне не очень нравится Инди :( Вроде все идет нормально, а потом мелкая пакасть с ее стороны губит самые хорошие идеи! :( Останавливает только то, что не хочется тратить время на реализацию интернет протоколов...


$hade   (2003-04-30 18:14:00) [26]

$hade © (30.04.03 17:54)
С чего бы это??

Это относилось к
>Это разные потоки.

Просто мы вместе пишем...:-)

А по поводу
>Zelius © (30.04.03 18:00)
...да...возможно это разные потоки...то есть вызов write во втором случае идет из основного потока...

Это работает...правильно работает...тока пока я не могу объяснить...:-)))
(за 12 часов сидения за компом уже плохо соображаю...:-((...
часа через 2 вылезу...пообчаемся на эту тему дальше...пошел пиво пить....


Zelius   (2003-04-30 18:00:00) [27]


> $hade © (30.04.03 17:54)

Потому что для того что бы воспользоваться контекстом потока TidPeerThread необходимо вставлять код в OnExecute. Ты проверь! Поставь бряк внутри OnExecute, посмотри в View \ Debug Windows \ Threads ID потока, а потом поставь бряк на твою отсылку данных и повтори тоже самое. Мне кажется, что это буду разные потоки.


$hade   (2003-04-30 17:54:00) [28]

С чего бы это??


Zelius   (2003-04-30 17:53:00) [29]


> $hade © (30.04.03 17:46)

Сорри, поторопился! Нет, конечно это один и тот же объект, но посылая данные так как ты указал, ты посылаешь их в контексте скорее всего главного потока!


Zelius   (2003-04-30 17:51:00) [30]


> $hade © (30.04.03 17:46)
> 2Bug
> а ты нет? объясни...:-)
>
> p:pointer;
> AThread:TIdPeerThread;
>
> p:=TObject(AThread);
> ...
> TIdPeerThread(p).Connection.write <-> AThread.Connection.write
>
> Это разные потоки??

Это разные потоки.


$hade   (2003-04-30 17:46:00) [31]

2Bug
а ты нет? объясни...:-)

p:pointer;
AThread:TIdPeerThread;

p:=TObject(AThread);
...
TIdPeerThread(p).Connection.write <-> AThread.Connection.write

Это разные потоки??



Bug   (2003-04-30 17:36:00) [32]

$hade © (30.04.03 17:18)
>>а зачем?? зачем из разных то?? ты сохраняешь указатель на
>>поток...и можеш обращаться к ЭТОМУ ЖЕ ПОТОКУ из любого места
>>через указатель...
ты уверен?


Zelius   (2003-04-30 17:34:00) [33]


> $hade © (30.04.03 17:18)

Конечно могу, но это не значит что посылка данных будет выполнена в контексте этого потока. В контексте потока код будет выполнен только тогда, когда он будет вызван из обработчика OnExecute. Или я что-то не понимаю...


$hade   (2003-04-30 17:18:00) [34]

>можно ли параллельно с одного и того же сокета посылать и принимать данные, причем из разных потоков???

а зачем?? зачем из разных то?? ты сохраняешь указатель на поток...и можеш обращаться к ЭТОМУ ЖЕ ПОТОКУ из любого места через указатель...


Zelius   (2003-04-30 17:08:00) [35]


> Reindeer Moss Eater (30.04.03 16:59)

А иногда им еще надо передавать произвольные данные! Например аська! Сервер не только получает сообщения от клиента, но и передает их ему, когда те появляются!


Zelius   (2003-04-30 17:04:00) [36]


> $hade © (30.04.03 16:50)

Я все понял кроме одного - можно ли параллельно с одного и того же сокета посылать и принимать данные, причем из разных потоков??? К сожалени, никак не могу найти статью на эту тему! Придется похоже руками пробовать...
По поводу кода, вместо ActiveClients я пользуюсь TcpServer.ThreadList, а вместо TClient я храню как раз данные в TMyidPeerThread, что вобщем одно и тоже.


$hade   (2003-04-30 17:03:00) [37]

2Reindeer Moss Eater
вполне согласен,но все же иногда надо что либо послать клиенту без его запроса...к примеру сообщение от админа сервера....в то время когда клиент заливает 50Mb файл на сервер...:-)


Reindeer Moss Eater   (2003-04-30 16:59:00) [38]

Дело конечно хозяйское, но TCP сервера работают примерно по такой схеме:
1. Дождаться запроса услуги от клиента
2. Выполнить запрос клиента, и отправить ему результат
3. Перейти к пункту 1.


Reindeer Moss Eater   (2003-04-30 16:50:00) [39]

... и приводит к блокированию потока! Чего я и хочу избежать!
И что тебе это даст?


$hade   (2003-04-30 16:50:00) [40]

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

Почему из разных то?? это один и тот же поток....
создавать 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;

Сильно запутанно...сорри...торопился...:-)


Страницы:   1 2 3 4

Наверх

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