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

Вниз

Передать массив клиенту TIdTCPClient   Найти похожие ветки 

 
vogel_max   (2007-07-26 12:38) [0]

Добрый день!
На форуме была эта тема, но понятного ответа или рабочего кода там нет.
Ничего не ругается просто не работает.
И ещё, как сделать чтобы сервер отправлял массив по требованию клиента без Disconnect постоянного. Т.к. отправлять надо будет постоянно, часто и очень много )

есть сервер, он должен отдавать клиентам массив данных:

procedure TForm1.ServerExecute(AThread: TIdPeerThread);
const ar : array[0..5] of char = ("A","B","C",#39,#00,"B");
var    t:TMemoryStream;
begin
try
 t := TMemoryStream.Create;
 t.Write(ar[0],sizeof(ar));
 t.Position := 0;
 Athread.Connection.WriteStream(t,false,false);
 AThread.Connection.Disconnect;
finally
 t.Free;
end;
end;

и клиент который сохраняет массив:

procedure TForm1.Button1Click(Sender: TObject);
var
t : TMemoryStream;
ar : array [0..5] of char;
begin
try
 t := TMemoryStream.Create;
 t.Position := 0;
 Client.Connect;
 Client.ReadStream(t,t.Size,false);
 Client.Disconnect;
 t.Position:=0;
 t.Read(ar,t.Size);
finally
 t.Free;
end;
end;


 
Сергей М. ©   (2007-07-26 12:42) [1]


> Client.ReadStream(t,t.Size,false);


Клиент у тебя говорит серверу - "дай 0 байт".

Ноль просил - ноль и получил)


 
Сергей М. ©   (2007-07-26 13:02) [2]

И к чему эти выкрутасы со стримами, если размер массива заранее известен и клиенту и серверу, тоже не понятно.

procedure TForm1.ServerExecute(AThread: TIdPeerThread);
const
 ar: array[0..5] of char = ("A","B","C",#39,#00,"B");
begin
..
Athread.Connection.WriteBuffer(ar, SizeOf(ar), True);
..
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 ar : array [0..5] of char;
begin
..
Client.ReadBuffer(ar, SizeOf(ar));
..
end;


 
vogel_max   (2007-07-26 14:05) [3]

Вы правы ) . Спасибо. Просто уже клинит. А как сделать чтобы сервер отправлял данные по сообщению?

Вроде

procedure TForm1.Button1Click(Sender: TObject);
var
t : TMemoryStream;
ar : array [0..5] of char;
begin
try
 t := TMemoryStream.Create;
 t.Position := 0;
 Client.Connect;
 Client.Write("send");                        // говорю серверу что жду
 Client.ReadStream(t,SizeOf(ar),true);


а серверу добавил:

procedure TForm1.ServerExecute(AThread: TIdPeerThread);
****
sCommand := AThread.Connection.ReadLn;
 if SameText(sCommand, "send") then
  begin
     *****  

но что то виснет


 
vogel_max   (2007-07-26 14:07) [4]

хм заменил
sCommand := AThread.Connection.ReadLn;
на
sCommand := AThread.Connection.ReadString(4);
заработало...
а как правильно? если команду любой длины захочется? )


 
Сергей М. ©   (2007-07-26 14:15) [5]


> хм заменил
> sCommand := AThread.Connection.ReadLn;
> на
> sCommand := AThread.Connection.ReadString(4);
> заработало...


А это здесь причем ?

В приведенном тобой коде нет на стороне сервера никаких Read-вызовов, да и клиент твой в этом коде ничего не передает серверу.


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


Что такое "команда" ?
Это содержимое того самого массива ?
А зачем для этого нужен массив ?
Поясни ..


 
Сергей М. ©   (2007-07-26 14:17) [6]


> vogel_max   (26.07.07 14:05) [3]


Да, теперь вижу.

Client.WriteLn("send");

sCommand := AThread.Connection.ReadLn;


 
vogel_max   (2007-07-27 08:37) [7]

Спасибо. Ещё вопрос. Сделал всё работает, но т.к. каждый раз connect а данные (2000 элементов массив) я читаю каждые пол секунды, то порт удалённый постоянно увеличивается. Сервер сваливается где то за полминуты, думаю из за этого.
Хочу сделать чтобы подключение было сделано один раз, а потом просто данные читать по таймеру. Вот что получилось (клиент при повторной попытке  Client.Write("send") уходит в finally):

клиент (сейчас перечитывает по нажатии button1, потом будет по таймеру):

procedure TForm1.Button4Click(Sender: TObject);
begin
Client.Connect;              // client: TIdTCPClient;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
t : TMemoryStream;
i: integer;
begin
try
 t := TMemoryStream.Create;
 t.Position := 0;
 client.;
 Client.Write("send");
 Client.ReadStream(t,SizeOf(data),true);
 t.Position:=0;
 t.Read(data,t.Size);
finally
 t.Free;
end;
end;

сервер:

procedure TForm1.ServerExecute(AThread: TIdPeerThread);
var
 t:TMemoryStream;
 sCommand: string;
begin
 sCommand := AThread.Connection.ReadString(4);
 if SameText(sCommand, "send") then
  begin
    Edit1.Text:= sCommand;
    try
     t := TMemoryStream.Create;
     t.Write(data,sizeof(data));
     t.Position := 0;
     Athread.Connection.WriteStream(t,false,false);
     t.Free;
    finally
     t.Free;
    end;
end;
end;


 
Сергей М. ©   (2007-07-27 09:23) [8]


> Хочу сделать чтобы подключение было сделано один раз, а
> потом просто данные читать по таймеру


Просто перенеси код из обработчика кнопки 1 в обработчик таймера.


> клиент при повторной попытке  Client.Write("send") уходит
> в finally


Это потому что сервер после выполнения обработчика OnExecute тут же разрывает соединение.

Необходимо поместить тело этого обработчика в while-цикл, завершающийся по условию PeerThread.Connection.Connected = False


 
vogel_max   (2007-07-27 11:11) [9]

сделал цикл, но тоже самое получается - клиент первый раз читает, на второй connection closed gracefully


procedure TForm1.ServerExecute(AThread: TIdPeerThread);
var
 t:TMemoryStream;
 sCommand: string;
begin
repeat
begin
 sCommand := AThread.Connection.ReadString(4);
 if SameText(sCommand, "send") then
  begin
    try
     t := TMemoryStream.Create;
     t.Write(data,sizeof(data));
     t.Position := 0;
     Athread.Connection.WriteStream(t,false,false);
     t.Free;
    finally
     t.Free;
    end;
  end;
end
until(AThread.Connection.Connected=false);
end;


 
Сергей М. ©   (2007-07-27 12:03) [10]


> на второй connection closed gracefully


А что говорит отладчик при трассировке ServerExecute ?


 
vogel_max   (2007-07-27 12:56) [11]

ругается при выполнении t.free во второй раз

......
t.Free;
   finally
    t.Free;
........


убрал первый вызов free - клиент данные не получает ошибка  - read timeout
убрал второй - тоже самое


 
Сергей М. ©   (2007-07-27 13:00) [12]

И долго ты экспериментировать вслепую будешь ?

Брейкпойнт на until-операторе ловишь или не ловишь ?


 
SlymRO ©   (2007-07-27 13:06) [13]

Двойной Free объекту!
procedure TForm1.ServerExecute(AThread: TIdPeerThread);
var
t:TMemoryStream;
sCommand: string;
begin
repeat
begin
sCommand := AThread.Connection.ReadString(4);
if SameText(sCommand, "send") then
 begin
   t := TMemoryStream.Create;
   try
    t.Write(data,sizeof(data));
    t.Position := 0;
    Athread.Connection.WriteStream(t,false,false);
   finally
    t.Free;
   end;
 end;
end
until(AThread.Connection.Connected=false);
end;


 
Сергей М. ©   (2007-07-27 14:08) [14]


> Двойной Free объекту


Он оба Free убрал , см. [11]

При этом у него другие чудеса начались)



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

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

Наверх




Память: 0.51 MB
Время: 0.017 c
2-1206829750
206196131
2008-03-30 01:29
2008.04.27
как же весь мир делает плагины к своим/чужим приложениям


2-1207311044
TCrash
2008-04-04 16:10
2008.04.27
Размеры меню


8-1178878045
VoKram
2007-05-11 14:07
2008.04.27
PostScript -> EMF


15-1205015585
Германн
2008-03-09 01:33
2008.04.27
Всё уже украдено, до нас.


15-1205071921
oleg_teacher
2008-03-09 17:12
2008.04.27
Орешник