我需要帮助来了解如何通过Indy TCP服务器/客户端传输记录.我有2个程序,我把客户端和另一个服务器.在客户端上我按下了一个按钮:客户端是TIdTCPClient
Client.Connect();
Run Code Online (Sandbox Code Playgroud)
在服务器端,我在ServerConnect事件上添加一行到客户端连接的备忘录
Protocol.Lines.Add(TimeToStr(Time)+' connected ');
Run Code Online (Sandbox Code Playgroud)
要从客户端发送数据,我有一条记录,我想发送:
Tmyrecord = record
IPStr: string[15];
end;
Run Code Online (Sandbox Code Playgroud)
我在那里有一个发送按钮:
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;
Run Code Online (Sandbox Code Playgroud)
在服务器端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
Run Code Online (Sandbox Code Playgroud)
我不知道为什么它不起作用,为什么我不能显示我从客户端写的IP地址.我想读取服务器端的记录(msRecInfo),我从客户端发送.我想访问我的记录元素,在这种情况下我想读取记录的IPSTR元素.当我从客户端按下发送按钮时,应用程序挂起,服务器部分.
非常感谢提前
Rem*_*eau 11
你正在犯一个经典的新手错误 - 你期望TIdIOHandler.Write(TStream)和TIdIOHandler.ReadStream()方法的默认行为相互匹配,但实际上并没有.
默认参数值TIdIOHandler.ReadStream()告诉它期望一个Integer或Int64(取决于TIdIOHandler.LargeStream属性的值)在流数据之前指定数据的长度.
但是,默认参数值TIdIOHandler.Write(TStream)不要告诉它发送任何这样的Integer/Int64值.因此,你使用TIdIOHandler.ReadStream()读取记录的前几个字节并将它们解释为Integer/Int64(926036233给出你发送的字符串值),然后等待那么多字节到达,这永远TIdIOHandler.ReadStream()不会退出(除非你将TIdIOHandler.ReadTimeout属性设置为非无限值).
您的代码中还存在一些使用TMemoryStreamIndy之外的对象的其他小错误/拼写错误.
试试这个:
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;
Run Code Online (Sandbox Code Playgroud)
或这个:
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;
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用发送记录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;
Run Code Online (Sandbox Code Playgroud)