gpt4 book ai didi

Delphi TidTCPServer 和 TidTCPClient 传输记录

转载 作者:行者123 更新时间:2023-12-03 14:51:49 25 4
gpt4 key购买 nike

我需要帮助来了解如何通过 Indy TCP 服务器/客户端传输记录。我有两个程序,一个是客户端,另一个是服务器。在客户端上的按钮上我放置了连接:客户端是 TIdTCPClient

Client.Connect();

在服务器端,我在 ServerConnect 事件上添加一行以备注客户端已连接

Protocol.Lines.Add(TimeToStr(Time)+' connected ');

要从客户端发送数据,我有一条记录,我想发送:

Tmyrecord = record
IPStr: string[15];
end;

我那里有一个发送按钮:

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;

在服务器端 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

我不知道为什么它不起作用,为什么我无法显示我从客户端编写的 IP 地址。我想在服务器端读取从客户端发送的记录(msRecInfo)。我想访问我的记录元素,在本例中我想读取我的记录的 IPSTR 元素。当我从客户端按下发送按钮时,应用程序挂起,服务器部分。

提前非常感谢

最佳答案

您犯了一个典型的新手错误 - 您期望 TIdIOHandler.Write(TStream)TIdIOHandler.ReadStream() 方法的默认行为彼此匹配,但实际上并没有。

TIdIOHandler.ReadStream() 的默认参数值告诉它期望一个 IntegerInt64(取决于 code>TIdIOHandler.LargeStream 属性)在流数据前面指定数据的长度。

但是,TIdIOHandler.Write(TStream) 的默认参数值不会告诉它发送任何此类 Integer/Int64 值。因此,您使用 TIdIOHandler.ReadStream() 读取记录的前几个字节并将它们解释为 Integer/Int64(即 926036233 > 给定您要发送的字符串值),然后等待那么多字节到达,这永远不会导致 TIdIOHandler.ReadStream() 不会退出(除非您设置了 TIdIOHandler.ReadTimeout 属性为非无限值)。

在使用 Indy 之外的 TMemoryStream 对象的代码中还存在一些其他小错误/拼写错误。

试试这个:

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;

或者这个:

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;

或者,您可以使用 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;

关于Delphi TidTCPServer 和 TidTCPClient 传输记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10874447/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com