[英]Delphi: (Indy) Send a header Record followed by a file
我目前正在尝试使用Indy在TCP之上编写自定义更高级别的协议。 本质上,我想跨(使用流)发送一条记录,但是该记录可以表明要跟随的x字节将是一个图像文件。
这样,当在服务器上接收到记录时,如果记录的内容指示其后跟有图像,则需要将记录和图像数据分开。
var
Segment: TDPPSegment;
Segment2: TDPPSegment;
Buffer: TIdBytes;
Buffer2: TIdBytes;
Mem: TMemoryStream;
begin
if (Client.Connected) then begin
Segment.NameStr := 'Adrian';
Segment2.NameStr := 'Jon';
Mem := TMemoryStream.Create;
Mem.Write(Segment, SizeOf(Segment));
Mem.Write(Segment2, SizeOf(Segment2));
//The Size of the stream is 8 bytes here!
Client.IOHandler.Write(Mem, 0, False);
结束;
为了模拟“图像文件”,我只想连续发送两个记录。 那就是目标。 请注意,这里我是一次发送整个内存流(!),而不是逐条记录。 但是有趣的是,服务器运行了两次OnExecute事件!
var
Buffer: TIdBytes;
Segment: TDPPSegment;
Mem: TMemoryStream;
begin
Mem := TMemoryStream.Create;
AContext.Connection.IOHandler.ReadStream(Mem, SizeOf(TDPPSegment), False);
//Incoming stream size is FOUR bytes but TWICE!
Mem.Position := 0;
Mem.Read(Segment, SizeOf(TDPPSegment));
Showmessage(Segment.NameStr);
我希望它执行一次,所以将来我可以先读取标头记录(已知大小),然后查看将要遵循的内容/并采取相应的措施。
帮助将不胜感激!
感谢您的阅读,阿德里安
您的记录中包含非ShortString字符串,这可以通过以下事实证明:字符数据占用的字节数大于写入流中的字节数-这意味着指针值(2 x SizeOf(Pointer))被写入流而不是实际字符。 因此,您将必须手动序列化字符串,例如发送字符串长度,然后发送实际字符。 而且,如果计划支持Delphi 2009+,则必须考虑Unicode,因此在传输字符串之前应该对其进行编码,然后在接收端对其进行解码。
记录对于组织内存中的数据很有用,但通常对于通过网络传输数据不是很方便,除非记录仅包含POD类型(并且字符串不符合此条件)。
尝试这个:
procedure WriteStrToIO(IO: TIdIOHandler; const S: String);
var
Buf: TIdBytes;
Len: Integer;
begin
Buf := ToBytes(S, IndyUTF8Encoding);
Len := Length(Buf);
IO.Write(Len);
if Len > 0 then IO.Write(Buf);
end;
var
Len: Integer;
Buf: TIdBytes; // or whatever you want to use...
begin
if Client.Connected then
begin
WriteStrToIO(Client.IOHandler, 'Adrian');
Buf := ...; // secondary data
Len := Length(Buf);
Client.IOHandler.Write(Len);
if Len > 0 then
Client.IOHandler.Write(Buf);
...
end;
end;
。
var
NameStr: String;
Buf: TIdBytes;
begin
with AContext.Connection.IOHandler do
begin
NameStr := ReadString(ReadInteger, IndyUTF8Encoding);
// read secondary data ...
ReadBytes(Buf, ReadInteger);
end;
// ShowMessage() is not thread-safe!
Windows.MessageBox(0, PChar(NameStr), 'NameStr', MB_OK);
end;
至于OnExecute
事件被多次触发,这是正常现象。 该事件根本与数据传输无关。 在连接的生命周期中,在连续循环中调用它。 退出事件处理程序后,如果客户端仍处于连接状态,则会立即再次触发它。 这对于像您这样的基于消息的协议很有用,在该协议中,事件被触发,读取一条消息等待数据到达,退出,再次触发以读取下一条消息等待数据到达,等等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.