You need to enable JavaScript to run this app. Delphi中如何通过Socket收发TList<TRect>类型的RectList对象
优惠活动
大模型
产品
解决方案
定价
更多

Delphi中如何通过Socket收发TList<TRect>类型的RectList对象

实现思路

因为TRect是固定大小的值类型,TList<TRect>内部存储的是连续的TRect结构数组,因此不需要复杂的对象序列化逻辑,只需要按照「先传元素数量、再传所有矩形二进制数据」的约定传输,接收端按照同样规则解析即可还原出同类型变量。

服务端(TServerSocket)发送实现

在需要触发发送的位置编写如下逻辑:

procedure TForm1.btnSendClick(Sender: TObject);
var
  ListCount: Integer;
  SendBuf: TBytes;
begin
  if RectList.Count = 0 then Exit;
  if ServerSocket1.Socket.ActiveConnections = 0 then Exit;

  // 构造发送缓冲区:前4字节存元素数量,后续存储所有TRect数据
  ListCount := RectList.Count;
  SetLength(SendBuf, SizeOf(Integer) + ListCount * SizeOf(TRect));
  // 拷贝元素数量到缓冲区头部
  Move(ListCount, SendBuf[0], SizeOf(Integer));
  // 拷贝所有矩形数据到缓冲区
  if ListCount > 0 then
    Move(RectList.List^, SendBuf[SizeOf(Integer)], ListCount * SizeOf(TRect));

  // 发送给第一个连接的客户端,多客户端场景可遍历Connections列表批量发送
  ServerSocket1.Socket.Connections[0].SendBuf(SendBuf[0], Length(SendBuf));
end;
客户端(TClientSocket)接收实现

首先在客户端窗体类中新增私有成员,用于处理TCP流的粘包/半包问题:

private
  FRecvBuf: TBytes; // 全局接收缓冲区
  FExpectedCount: Integer; // 待接收的矩形数量,-1表示未收到长度头

窗体初始化时对变量赋值:

procedure TClientForm.FormCreate(Sender: TObject);
begin
  FExpectedCount := -1;
  SetLength(FRecvBuf, 0);
  ClientSocket1.Active := True;
end;

在TClientSocket的OnRead事件中编写解析逻辑:

procedure TClientForm.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
  RecvLen: Integer;
  TempBuf: array[0..4095] of Byte;
  P: PByte;
  NewRectList: TList<TRect>;
begin
  // 读取当前Socket可读的数据
  RecvLen := Socket.ReceiveBuf(TempBuf, SizeOf(TempBuf));
  if RecvLen <= 0 then Exit;

  // 新数据追加到全局接收缓冲区
  SetLength(FRecvBuf, Length(FRecvBuf) + RecvLen);
  Move(TempBuf, FRecvBuf[Length(FRecvBuf) - RecvLen], RecvLen);

  P := @FRecvBuf[0];
  while True do
  begin
    // 先解析4字节的长度头
    if FExpectedCount = -1 then
    begin
      if Length(FRecvBuf) < SizeOf(Integer) then Break; // 长度不足,等待后续数据
      Move(P^, FExpectedCount, SizeOf(Integer));
      Inc(P, SizeOf(Integer));
      Delete(FRecvBuf, 0, SizeOf(Integer)); // 移除已处理的长度头
    end;

    // 解析矩形数据
    if FExpectedCount >= 0 then
    begin
      if Length(FRecvBuf) < FExpectedCount * SizeOf(TRect) then Break; // 数据不足,等待后续数据
      // 构造还原后的TList<TRect>
      NewRectList := TList<TRect>.Create;
      NewRectList.Count := FExpectedCount; // 预先分配空间
      Move(P^, NewRectList.List^, FExpectedCount * SizeOf(TRect));
      // 此处可将NewRectList赋值给你的业务变量使用,用完记得释放

      // 清理已处理的数据,重置状态
      Delete(FRecvBuf, 0, FExpectedCount * SizeOf(TRect));
      FExpectedCount := -1;
      NewRectList.Free; // 若已赋值给全局变量可删除此行
    end;
  end;
end;
注意事项
  • 该方案仅适用于两端均为Delphi开发的Windows场景,Windows平台下所有Delphi版本的TRect内存布局完全一致(4个Longint字段,顺序为Left/Top/Right/Bottom,大小16字节)
  • 若需要跨平台/跨语言通信,可在发送时将每个TRect的四个字段转为网络字节序,接收后转回本地字节序即可
  • 示例仅演示单个客户端的收发逻辑,多客户端场景遍历ServerSocket.Socket.Connections列表批量发送即可

内容的提问来源于stack exchange,提问作者user13342561

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 08:39:04