![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как получить сообщение от TCPServera? [D7, WinXP]
Anton. © (2004-06-09 16:06:00)Проблема такая отправляю сообщение на сервер
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
IdTCPClient1.WriteLn(‘М'+Memo2.Text);
end;
на сервере обработчик
if Msg[1]='M' then
begin
BroadcastMessage('E', 'New Message');
End;
Как клиенту получить это сообщение, делать ReadLn по таймеру?
Петров (2004-06-22 17:53:00) [1]Да, признаю свою ошибку.
alienserg (2004-06-18 02:40:00) [2]Петров (15.06.04 13:31) [31]
буферы для ReadLn и WriteLn разные.
FInputBuffer: TIdManagedBuffer;
FWriteBuffer: TIdSimpleBuffer;
Петров (2004-06-15 13:31:00) [3]Когда TIdTcpClient делает ReadLn, он обращается к внутреннему буферу Indy. Поэтому, читая без задержки (не дожидаясь отправки серверу), легко можно считать свое же сообщение, посланное серверу тем же самым клиентом перед этим через TIdTcpClient.WriteLn!
колька (2004-06-14 04:37:00) [4]if client1.LastCmdResult.Text.Text = 'ok' then
поменять на
if client1.readln = 'ok' then
колька (2004-06-14 03:54:00) [5]В else кидай
asender.Thread.Connection.WriteLn('no');
в клеенте обработчик:
case if client1.LastCmdResult.Text.Text of
'ok':readin(buf);
'no':exit;
колька (2004-06-14 03:47:00) [6]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.Server1Command1 numb(ASender: TIdCommand);
begin
if mass = true then begin
asender.Thread.Connection.WriteLn(ok);
asender.Thread.Connection.WriteLn('нужная строка);
end else begin
exit;
end;
alienserg (2004-06-14 02:44:00) [7]колька (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-12 23:44:00) [8]Может я не доганяю, но клиент на то и клиент что б спращивать.
ИМХО сервер никак не сможет произвольно послать клиенту дату. Просто клиент не опрашивает порт, лишь на время timeout`а, ожидая ответ сервера. Можно конечно и порт слушать и коннект ловить, но это помоему уже будет сервер, а не клиент.
Digitman (2004-06-11 08:18:00) [9]
> Verg © (10.06.04 18:14) [23]
> где народ берет этот шаблон Execute
ну где ж ? разумеется, здесь же , в статьях...
некто Карих Николай в свое время подсуетился неудачно ...
хотя ... обвинять его во всех смертных грехах тоже вроде бы нет повода - там ведь в статье как раз слово "шаблон" явно фигурирует ...
Антон. (2004-06-10 18:29:00) [10]Спасибо ошибки понял, учту
Verg (2004-06-10 18:14:00) [11]
> [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. Эта "рыба" плохо пахнет...
Digitman (2004-06-10 18:02:00) [12]
> ваши оценки?
твердый кол
за абсолютно бездумное сдирание кода метода
TMyThread1.Execute;
Anton. (2004-06-10 17:56:00) [13]что то вроде получилось, ваши оценки?
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;
Verg (2004-06-10 11:56:00) [14]
> 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 11:47:00) [15]В примерах DELPHI есть программка NETCHAT вот там на форме лежит как клиентский компонент так и серверный
Digitman (2004-06-10 11:47:00) [16]
> Когда и в какой момент второму клиенту надо вызывать IdTCPClient1.ReadLn
в тот момент, когда этот клиент желает получить потенциально отправляемое сервером строковое сообщение
> опрашивать сервер через промежутки времени?
это еще зачем ? ты расчитываешь что-то получить от сервера ? ну так и вызывай ReadLn() ! Как только сервер сподобится тебе что-то послать, ф-ция возвратит управление и вернет результирующу полученную от сервера строку
Anton. (2004-06-10 11:38:00) [17]Когда и в какой момент второму клиенту надо вызывать IdTCPClient1.ReadLn, опрашивать сервер через промежутки времени?
Digitman (2004-06-10 11:23:00) [18]
> получил сразу же отклик
правильно, получил ..
потому что IdTCPClient1.ReadLn выполнил
а тот (другой) клиент, который в этот момент "бил баклуши", не вызывая IdTCPClient1.ReadLn, разумеется, ничего не получил .. а с какого перепугу он что-то получить должен был. если даже пальцем не пошевелил ? законнектился и сидит себе ждет у моря погоды ?
"спрашивающий да получит ответ"(с)
Anton. (2004-06-10 11:16:00) [19]дальше запустил два клиента, один набрал сообщение и нажал кнопку
procedure TForm1.BitBtn1Click(Sender: TObject);
var Response : string;
begin
IdTCPClient1.WriteLn(Memo2.Text);
Response:=IdTCPClient1.ReadLn;
end;
получил сразу же отклик, второй сидит ничего не получив. Или получил да я не смог обработать прием?
Digitman (2004-06-10 11:05:00) [20]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;