I need help in understanding how to transfer a record through Indy TCP Server/Client. I have 2 programs, in I put client and in another server.
On client on a button I put connect : Client is TIdTCPClient
Client.Connect();
And at server side I am adding a line to memo that client is connected , on ServerConnect event
Protocol.Lines.Add(TimeToStr(Time)+' connected ');
To send data from client I have a record, which I want to send :
Tmyrecord = record
IPStr: string[15];
end;
And I have a send button there :
procedure Tform1.ButtonSendClick(Sender: TObject);
var
MIRec: Tmyrecord;
msRecInfo: TMemoryStream;
begin
MIRec.IPStr := '172.0.0.1';
msRecInfo := TMemoryStream.Create;
msRecInfo.Write(MIRec, SizeOf(MIRec));
msRecInfo.Position := 0;
Client.IOHandler.Write(msRecInfo);
end;
At server side onexecute I have the following code , I have same tmyrecord declared at server side too :
procedure TServerFrmMain.ServerExecute(AContext: TIdContext);
var
MIRec: Tmyrecord;
msRecInfo: TMemoryStream;
begin
if AContext.Connection.Connected then
begin
AContext.Connection.IOHandler.CheckForDataOnSource(10);
if not AContext.Connection.IOHandler.InputBufferIsEmpty then
begin
msRecInfo:= TMemoryStream.Create;
AContext.Connection.IOHandler.ReadStream(msRecInfo);
msRecInfo.Read(MIRec, sizeOf(msRecInfo));
ShowMessage(MIRec.IPStr);
end;
end;
end
I dont know why it is not working, why I cant show IP adress which I wrote from client side.
I want to read a record (msRecInfo) on server side which I am sending from client side. I want to access my record elements, in this case I want to read IPSTR element of my record. When I press send button from a client side, application hangs, server part.
Thanks a lot in advance
You are making a classic newbie mistake – you are expecting the default behaviors of the
TIdIOHandler.Write(TStream)andTIdIOHandler.ReadStream()methods to match each other, but they actually do not.The default parameter values of
TIdIOHandler.ReadStream()tell it to expect anIntegerorInt64(depending on the value of theTIdIOHandler.LargeStreamproperty) to preceed the stream data to specify the length of the data.However, the default parameter values of
TIdIOHandler.Write(TStream)do not tell it to send any suchInteger/Int64value. Thus, your use ofTIdIOHandler.ReadStream()reads the first few bytes of the record and interprets them as anInteger/Int64(which is926036233given the string value you are sending), and then waits for that many bytes to arrive, which never will soTIdIOHandler.ReadStream()does not exit (unless you set theTIdIOHandler.ReadTimeoutproperty to a non-infinite value).There are also some other minor bugs/typos in your code that uses the
TMemoryStreamobjects outside of Indy.Try this instead:
Or this:
Alternatively, you can send the record using
TIdBytesinstead ofTStream: