Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.08.22;
Скачать: CL | DM;

Вниз

Как получить сообщение от TCPServera?   Найти похожие ветки 

 
Anton.   (2004-06-09 16:06) [0]

Проблема такая отправляю сообщение на сервер
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
 IdTCPClient1.WriteLn(‘М"+Memo2.Text);
end;
на сервере обработчик
 if Msg[1]="M" then
  begin
   BroadcastMessage("E", "New Message");
  End;
Как клиенту получить это сообщение, делать ReadLn по таймеру?


 
Reindeer Moss Eater ©   (2004-06-09 16:32) [1]

procedure TForm1.BitBtn1Click(Sender: TObject);
var Response : string;
begin
IdTCPClient1.WriteLn(‘М"+Memo2.Text);
Response:=IdTCPClient1.ReadLn;
end;


 
Anton.   (2004-06-09 17:12) [2]

а если клиентов 2, то второй получает сообщение, только послав запрос серверу. как сделать что бы он автоматом принял? т.е один послал, на всех остальных клиентах отразилось?


 
Reindeer Moss Eater ©   (2004-06-09 17:25) [3]

Клиент посылает сообщение серверу, а не другим клиентам.
Что бы другие клиенты увидели сообщение нужно чтобы сервер отправил это сообщение этим клиентам


 
Digitman ©   (2004-06-09 17:31) [4]


> а если клиентов 2


да хоть 2 миллиона !


> второй получает сообщение, только послав запрос серверу


это в отношении [1] ? не нужно интерпретировать ПРИМЕР столь буквально ...


 
Anton.   (2004-06-09 18:04) [5]

Как можно отправить сообщение от сервера к клиенту? Что то я нигде таких примеров не нахожу


 
Digitman ©   (2004-06-10 08:20) [6]


> Что то я нигде таких примеров не нахожу


ну разумеется ... а набрать в справке по Инди-компонентам, например, ключ.слово "WriteLn" да посмотреть, какие Инди-классы имеют этот метод  - не царское это дело ..


 
Anton.   (2004-06-10 08:50) [7]

Чесно смотрел, но если клиент отправит серверу сообщение WriteLn, то клиент его получит только опросив сервер, так?


 
Reindeer Moss Eater ©   (2004-06-10 09:33) [8]

Если отвечающий ответит на вопрос спрашивающего, то спрашивающий будет знать ответ только услышав отвечающего.
Так? Или может иначе?


 
Anton.   (2004-06-10 09:49) [9]

нет вопрос в другом как осуществить широковешательное сообщение, то есть например один клиент послал серверу сообщение, и об этом сразу же должны знать все клиенты подсоедененные к серверу. Делать это по таймеру опрашивать всем сервер, или ставить TCP клиент и TCP сервер на одно приложение?


 
Artem03   (2004-06-10 09:54) [10]

Я у себя реализовал это по таймеру, т.е. после посылки сообщения на сервер (IdTCPServer) мой клиент ждет 1,5 секунды (как сказала одна барышня: "Шоб на верняка"), а затем принимает информацию от сервера.
Касательно сервера. У него есть событие
OnExecute(AThread: TIdPeerThread), где AThread ОДНОЗНАЧНО ИДЕНТИФИЦИРУЕТ источник получения информации (IdTCPClient"а, короче). А потому, вешаешь на это событие нужный тебе код и вперед.
А у параметра AThread есть куча всяких свойств, Например - Connection (соединение, ВЫЗВАВШЕЕ метод OnExecute).
У него есть методы Write...(написать клиенту) и Read...(прочитать от клиента). Так что успехов.


 
Reindeer Moss Eater ©   (2004-06-10 09:55) [11]

При чем здесь таймер?
Зачем он?

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


 
Digitman ©   (2004-06-10 10:15) [12]


> Anton.   (10.06.04 09:49) [9]


объект TIdTCPServer  имеет св-во Threads: TThreadList, это список объектов класса TIdPeerThread, каждый из которых ассоциирован с активным клиентом

объект TIdPeerThread имеет св-во Connection:  TIdTCPServerConnection

объект Connection имеет метод WriteLn()


 
Anton.   (2004-06-10 10:54) [13]

хорошо вот такой код отправит сообщения все подключенным на данный момент клиентам?
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
 Msg : string;
 Count: Integer;
begin
 Msg    := AThread.Connection.ReadLn;
 for Count := 0 to IdTCPServer1.Threads.LockList.Count -1 do
   TIdPeerThread(IdTCPServer1.Threads.LockList.Items[Count]).Connection.WriteLn(Msg);
 IdTCPServer1.Threads.UnlockList;


 
Digitman ©   (2004-06-10 11:05) [14]

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
i: Integer;
Msg : string;
begin
Msg    := AThread.Connection.ReadLn;
with AThread.Connection.Server.Threads.LockList do
try
 for i := 0 to Count -1 do
  try
   TIdPeerThread(Items[i]).Connection.WriteLn(Msg);
  except
  end;
finally
  IdTCPServer1.Threads.UnLockList;
end;
end;


 
Anton.   (2004-06-10 11:16) [15]

дальше запустил два клиента, один набрал сообщение и нажал кнопку
procedure TForm1.BitBtn1Click(Sender: TObject);
var Response : string;
begin
IdTCPClient1.WriteLn(Memo2.Text);
Response:=IdTCPClient1.ReadLn;
end;
получил сразу же отклик, второй сидит ничего не получив. Или получил да я не смог обработать  прием?


 
Digitman ©   (2004-06-10 11:23) [16]


> получил сразу же отклик


правильно, получил ..
потому что IdTCPClient1.ReadLn выполнил

а тот (другой) клиент, который в этот момент "бил баклуши", не вызывая IdTCPClient1.ReadLn, разумеется, ничего не получил .. а с какого перепугу он что-то получить должен был. если даже пальцем не пошевелил ? законнектился и сидит себе ждет у моря погоды ?

"спрашивающий да получит ответ"(с)


 
Anton.   (2004-06-10 11:38) [17]

Когда и в какой момент второму клиенту надо вызывать IdTCPClient1.ReadLn, опрашивать сервер через промежутки времени?


 
Digitman ©   (2004-06-10 11:47) [18]


> Когда и в какой момент второму клиенту надо вызывать IdTCPClient1.ReadLn


в тот момент, когда этот клиент желает получить  потенциально отправляемое сервером строковое сообщение


> опрашивать сервер через промежутки времени?


это еще зачем ? ты расчитываешь что-то получить от сервера ? ну так и вызывай ReadLn() ! Как только сервер сподобится тебе что-то послать, ф-ция возвратит управление и вернет результирующу полученную от сервера строку


 
Anton.   (2004-06-10 11:47) [19]

В примерах DELPHI есть программка NETCHAT вот там на форме лежит как клиентский компонент так и серверный


 
Verg ©   (2004-06-10 11:56) [20]


> Anton.   (10.06.04 11:47) [19]
> В примерах DELPHI есть программка NETCHAT вот там на форме
> лежит как клиентский компонент так и серверный


Ну и что?

> Anton.   (10.06.04 11:38) [17]
> Когда и в какой момент второму клиенту надо вызывать IdTCPClient1.ReadLn,
> опрашивать сервер через промежутки времени?


Да не сервер опрашивать! А свой сокет, подключенный к серверу.
Хоть через промежутки времени, хоть в отдельном потоке, хоть сразу же и readln делай, а на форму кинь antifreez... Дело вкуса и соответствия задаче.
Но, IdTCPClient не имеет возможности асинхронно, самостоятельно сообщить, что в его сокете появились какие-то принятые данные.


 
Anton.   (2004-06-10 17:56) [21]

что то вроде получилось, ваши оценки?

procedure TForm1.FormCreate(Sender: TObject);
var
 MyThread: TThread;
begin
 IdTCPClient1.Connect;
 T1 := TMyThread1.Create(False);
 T1.Priority := tpLowest;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 IdTCPClient1.Disconnect;
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
 close;
end;

procedure TForm1.ListenServer;
begin
 Memo1.Text:=IdTCPClient1.ReadLn;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
 IdTCPClient1.WriteLn("M"+Memo2.Text);
 Memo2.Clear;
 ListenServer;
end;

procedure TMyThread1.Execute;
begin
 while not Terminated do
  Synchronize(DoWork);
end;

procedure TMyThread1.DoWork;
begin
 Form1.ListenServer;
end;


 
Digitman ©   (2004-06-10 18:02) [22]


> ваши оценки?


твердый кол

за абсолютно бездумное сдирание кода метода
TMyThread1.Execute;


 
Verg ©   (2004-06-10 18:14) [23]


> [21] Anton.   (10.06.04 17:56)
> что то вроде получилось, ваши оценки?
>
> procedure TForm1.FormCreate(Sender: TObject);
> var
>  MyThread: TThread;
> begin
>  Memo2.Clear;
>  IdTCPClient1.Connect;
>  T1 := TMyThread1.Create(False);
> end;
>
> procedure TForm1.FormClose(Sender: TObject; var Action:
> TCloseAction);
> begin
>  IdTCPClient1.Disconnect;
> end;
>
> procedure TForm1.BitBtn2Click(Sender: TObject);
> begin
>  close;
> end;
>

> procedure TForm1.BitBtn1Click(Sender: TObject);
> begin
>  IdTCPClient1.WriteLn("M"+Memo1.Text);
> end;
>
> procedure TMyThread1.Execute;
> begin
>  while not Terminated do
   begin
      NewS := IdTCPClient1.ReadLn;
      if NewS <> "" then
        Synchronize(Show_NewS);
   end;
> end;
>
> procedure TMyThread1.Show_NewS;
> begin
     Memo1.Lines.Add(NewS);
> end;


NewS : string; - поле TMyThread1

P.S. А где народ берет этот шаблон Execute: while not Terminated do Synchronize(DoWork) ?
P.P.S. Эта "рыба" плохо пахнет...


 
Антон.   (2004-06-10 18:29) [24]

Спасибо ошибки понял, учту


 
Digitman ©   (2004-06-11 08:18) [25]


> Verg ©   (10.06.04 18:14) [23]


> где народ берет этот шаблон Execute


ну где ж ? разумеется, здесь же , в статьях...

некто Карих Николай в свое время подсуетился неудачно ...
хотя ... обвинять его во всех смертных грехах тоже вроде бы нет повода - там ведь в статье как раз слово "шаблон" явно фигурирует ...


 
колька   (2004-06-12 23:44) [26]

Может я не доганяю, но клиент на то и клиент что б спращивать.
ИМХО сервер никак не сможет произвольно послать клиенту дату. Просто клиент не опрашивает порт, лишь на время timeout`а, ожидая ответ сервера. Можно конечно и порт слушать и коннект ловить, но это помоему уже будет сервер, а не клиент.


 
alienserg   (2004-06-14 02:44) [27]

колька   (12.06.04 23:44) [26]

сервер может послать сообщение клиенту например по приходу сообщения от другого клиента. Это сообщение попадает в пункт назначения и сидит в TCP стеке и ждет, когда тамошний клент его опросит, выполнив ReadLn например.
Когда TIdTcpClient делает ReadLn, он обращается именно к локальному TCP стеку, а не к серверу.
Во всех примерах, поставляемых с Indy, стандартный прием работы с TIdTcpClient - опрос по таймеру(ReadLn, ReadInteger и т.д.). Например раз в 200 миллисекунд.
Обязательно ставьте на форму TIdAntifreeze, одно на приложение, иначе форма будет "замораживаться", поскольку Indy сокеты работают в блокирующем режиме.
Если вы используете TIdTcpServer и что-то хотите отрисовать на формах по событию OnExecute, то обязательно делайте Synchronize() или используйте для этого дела TIdSync.
Тот же самый принцип и для работы с базой данных. Создавайте/уничтожайте экземпляр датамодуля при каждом запросе или используйте единственный датамодуль, проставляя критические секции или создавайте пул датамодулей и регулируйте их выдачу тредам семафорами. Точнее не датамодулей а наборов dbconnection+dbqueries.


 
колька   (2004-06-14 03:47) [28]

alienserg  (14.06.04 02:44) [27]
>Это сообщение попадает в пункт назначения и сидит в TCP стеке и
>ждет, когда тамошний клент его опросит, выполнив ReadLn
>например.

Клиенту всеже придется опросить сервер.
Тогда можно сделать вот так:
клиент (по таймеру) опрашивает сервер на предмет появления для него(клиента) нового сообщения.
client1.SendCmd("numb");
if client1.LastCmdResult.Text.Text = "ok" then
readin(buf);
Сервер.
var
mess: boolean;
procedure TForm1.Server1Command1numb(ASender: TIdCommand);
begin
if mass = true then begin
asender.Thread.Connection.WriteLn(ok);
asender.Thread.Connection.WriteLn("нужная строка);
end else begin
exit;
end;


 
колька   (2004-06-14 03:54) [29]

В else кидай
asender.Thread.Connection.WriteLn("no");
в клеенте  обработчик:
case if client1.LastCmdResult.Text.Text of
"ok":readin(buf);
"no":exit;


 
колька   (2004-06-14 04:37) [30]

if client1.LastCmdResult.Text.Text = "ok" then
поменять на
if client1.readln = "ok" then


 
Петров   (2004-06-15 13:31) [31]

Когда TIdTcpClient делает ReadLn, он обращается к внутреннему буферу Indy. Поэтому, читая без задержки (не дожидаясь отправки серверу), легко можно считать свое же сообщение, посланное серверу тем же самым клиентом перед этим через TIdTcpClient.WriteLn!


 
alienserg   (2004-06-18 02:40) [32]

Петров   (15.06.04 13:31) [31]

буферы для ReadLn и WriteLn разные.
FInputBuffer: TIdManagedBuffer;
FWriteBuffer: TIdSimpleBuffer;


 
Петров   (2004-06-22 17:53) [33]

Да, признаю свою ошибку.



Страницы: 1 вся ветка

Текущий архив: 2004.08.22;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.04 c
3-1091137474
Максим
2004-07-30 01:44
2004.08.22
Access - как измененить значение поля?


8-1086346750
Kein
2004-06-04 14:59
2004.08.22
правильное масштабирование изображений


4-1089605641
DION
2004-07-12 08:14
2004.08.22
Инфо по винту...


14-1091186602
WondeRu
2004-07-30 15:23
2004.08.22
Какая часть Вашего дохода уходит на "поддержание"...


4-1089279091
DelphiNew
2004-07-08 13:31
2004.08.22
TreeView в чужом приложении