You are making a classic novice mistake - you expect that the default behavior of the TIdIOHandler.Write(TStream)
and TIdIOHandler.ReadStream()
methods will match, but they donโt actually do this.
The default values โโof TIdIOHandler.ReadStream()
indicate that he should expect Integer
or Int64
(depending on the value of the TIdIOHandler.LargeStream
property) to chase stream data to indicate the length of the data.
However, the default parameter values TIdIOHandler.Write(TStream)
do not tell him to send such an Integer/Int64
value. So your use of TIdIOHandler.ReadStream()
reads the first few bytes of the record and interprets them as Integer/Int64
(which is 926036233
given the string value you are sending) and then waits for so many bytes to arrive that there will never be a TIdIOHandler.ReadStream()
does not exit (unless you set the TIdIOHandler.ReadTimeout
property to an infinite value).
There are other minor bugs / typos in the code that use TMemoryStream
objects outside of Indy.
Try this instead:
procedure Tform1.ButtonSendClick(Sender: TObject); var MIRec: Tmyrecord; msRecInfo: TMemoryStream; begin MIRec.IPStr := '172.0.0.1'; msRecInfo := TMemoryStream.Create; try msRecInfo.Write(MIRec, SizeOf(MIRec)); // writes the stream size then writes the stream data Client.IOHandler.Write(msRecInfo, 0, True); finally msRecInfo.Free; end; end; procedure TServerFrmMain.ServerExecute(AContext: TIdContext); var MIRec: Tmyrecord; msRecInfo: TMemoryStream; begin msRecInfo := TMemoryStream.Create; try // reads the stream size then reads the stream data AContext.Connection.IOHandler.ReadStream(msRecInfo, -1, False); msRecInfo.Position := 0; msRecInfo.Read(MIRec, SizeOf(MIRec)); ... finally msRecInfo.Free; end; end;
Or that:
procedure Tform1.ButtonSendClick(Sender: TObject); var MIRec: Tmyrecord; msRecInfo: TMemoryStream; begin MIRec.IPStr := '172.0.0.1'; msRecInfo := TMemoryStream.Create; try msRecInfo.Write(MIRec, SizeOf(MIRec)); // does not write the stream size, just the stream data Client.IOHandler.Write(msRecInfo, 0, False); finally msRecInfo.Free; end; end; procedure TServerFrmMain.ServerExecute(AContext: TIdContext); var MIRec: Tmyrecord; msRecInfo: TMemoryStream; begin msRecInfo := TMemoryStream.Create; try // does not read the stream size, just the stream data AContext.Connection.IOHandler.ReadStream(msRecInfo, SizeOf(MIRec), False); msRecInfo.Position := 0; msRecInfo.Read(MIRec, SizeOf(MIRec)); ... finally msRecInfo.Free; end; end;
Alternatively, you can send a record using TIdBytes
instead of TStream
:
procedure Tform1.ButtonSendClick(Sender: TObject); var MIRec: Tmyrecord; Buffer: TIdBytes; begin MIRec.IPStr := '172.0.0.1'; Buffer := RawToBytes(MIRec, SizeOf(MIRec)); Client.IOHandler.Write(Buffer); end; procedure TServerFrmMain.ServerExecute(AContext: TIdContext); var MIRec: Tmyrecord; Buffer: TIdBytes; begin AContext.Connection.IOHandler.ReadBytes(Buffer, SizeOf(MIRec)); BytesToRaw(Buffer, MIRec, SizeOf(MIRec)); ... end;