Форум: "Сети";
Текущий архив: 2004.08.22;
Скачать: [xml.tar.bz2];
ВнизКак получить сообщение от 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;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.031 c