[英]Delphi TidTCPServer and TidTCPClient transferring a record
I need help in understanding how to transfer a record through Indy TCP Server/Client. 我需要帮助来了解如何通过Indy TCP服务器/客户端传输记录。 I have 2 programs, in I put client and in another server.
我有2个程序,我把客户端和另一个服务器。 On client on a button I put connect : Client is TIdTCPClient
在客户端上我按下了一个按钮:客户端是TIdTCPClient
Client.Connect();
And at server side I am adding a line to memo that client is connected , on ServerConnect event 在服务器端,我在ServerConnect事件上添加一行到客户端连接的备忘录
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 : 在服务器端onexecute我有以下代码,我在服务器端也声明了相同的tmyrecord:
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. 我不知道为什么它不起作用,为什么我不能显示我从客户端写的IP地址。 I want to read a record (msRecInfo) on server side which I am sending from client side.
我想读取服务器端的记录(msRecInfo),我从客户端发送。 I want to access my record elements, in this case I want to read IPSTR element of my record.
我想访问我的记录元素,在这种情况下我想读取记录的IPSTR元素。 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)
and TIdIOHandler.ReadStream()
methods to match each other, but they actually do not. 您正在犯一个经典的新手错误 - 您期望
TIdIOHandler.Write(TStream)
和TIdIOHandler.ReadStream()
方法的默认行为相互匹配,但它们实际上并不相同。
The default parameter values of TIdIOHandler.ReadStream()
tell it to expect an Integer
or Int64
(depending on the value of the TIdIOHandler.LargeStream
property) to preceed the stream data to specify the length of the data. TIdIOHandler.ReadStream()
的默认参数值告诉它期望Integer
或Int64
(取决于TIdIOHandler.LargeStream
属性的值)在流数据之前指定数据的长度。
However, the default parameter values of TIdIOHandler.Write(TStream)
do not tell it to send any such Integer/Int64
value. 但是,
TIdIOHandler.Write(TStream)
的默认参数值不会告诉它发送任何此类Integer/Int64
值。 Thus, your use of TIdIOHandler.ReadStream()
reads the first few bytes of the record and interprets them as an Integer/Int64
(which is 926036233
given the string value you are sending), and then waits for that many bytes to arrive, which never will so TIdIOHandler.ReadStream()
does not exit (unless you set the TIdIOHandler.ReadTimeout
property to a non-infinite value). 因此,您使用
TIdIOHandler.ReadStream()
读取记录的前几个字节并将它们解释为Integer/Int64
(给定您发送的字符串值为926036233
),然后等待那么多字节到达,从来没有这样TIdIOHandler.ReadStream()
不会退出(除非您将TIdIOHandler.ReadTimeout
属性设置为非无限值)。
There are also some other minor bugs/typos in your code that uses the TMemoryStream
objects outside of Indy. 您的代码中还有一些其他小错误/拼写错误,它们使用Indy之外的
TMemoryStream
对象。
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 this: 或这个:
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 the record using TIdBytes
instead of TStream
: 或者,您可以使用
TIdBytes
而不是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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.