TCP发送接收json格式

当使用Delphi通过TCP协议传输JSON格式的数据,并且每包数据的长度不固定时,处理分包和多包的情况变得更加复杂。在这种情况下,通常的做法是在每个JSON消息前后添加特定的分隔符(如`{}`、`\n`等),以便接收端能够正确地识别和解析这些消息。
以下是一个示例,展示了如何在Delphi中实现这一机制:
1. 发送端:在每个JSON消息后附加一个分隔符(例如换行符 `\n`)。
2. 接收端:读取数据并根据分隔符来分割和解析JSON消息。
发送端代码

uses
  System.SysUtils, IdTCPClient, System.JSON;

procedure SendJsonData(const AClient: TIdTCPClient; const AJsonObject: TJSONObject);
var
  JsonString: string;
begin
  // 将JSON对象转换为字符串
  JsonString := AJsonObject.ToString;

  // 发送消息内容,并在末尾添加换行符作为分隔符
  AClient.IOHandler.WriteLn(JsonString);
end;

// 示例调用
procedure TForm1.ButtonSendClick(Sender: TObject);
var
  JsonObject: TJSONObject;
begin
  JsonObject := TJSONObject.Create;
  try
    JsonObject.AddPair('key1', 'value1');
    JsonObject.AddPair('key2', 'value2');

    SendJsonData(IdTCPClient1, JsonObject);
  finally
    JsonObject.Free;
  end;
end;


接收端代码

uses
  System.SysUtils, IdTCPServer, System.JSON, System.Classes;

type
  TMessageBuffer = class
  private
    FBuffer: TStringList;
  public
    constructor Create;
    destructor Destroy; override;
    procedure AddData(const Data: string);
    function GetCompleteMessages: TArray<string>;
  end;

constructor TMessageBuffer.Create;
begin
  inherited Create;
  FBuffer := TStringList.Create;
end;

destructor TMessageBuffer.Destroy;
begin
  FBuffer.Free;
  inherited Destroy;
end;

procedure TMessageBuffer.AddData(const Data: string);
begin
  FBuffer.Text := FBuffer.Text + Data;
end;

function TMessageBuffer.GetCompleteMessages: TArray<string>;
var
  Lines: TStringDynArray;
  I: Integer;
  CompleteMessages: TArray<string>;
begin
  SetLength(CompleteMessages, 0);

  // 分割缓冲区中的每一行
  Lines := SplitString(FBuffer.Text, #13#10); // 处理Windows风格的换行符
  if Length(Lines) > 0 then
  begin
    for I := Low(Lines) to High(Lines) do
    begin
      if Trim(Lines[I]) <> '' then
      begin
        SetLength(CompleteMessages, Length(CompleteMessages) + 1);
        CompleteMessages[High(CompleteMessages)] := Lines[I];
      end;
    end;
    // 清空已处理的部分
    FBuffer.Clear;
  end;

  Result := CompleteMessages;
end;

procedure ReceiveJsonData(AContext: TIdContext; AMessageBuffer: TMessageBuffer);
var
  Data: string;
  Messages: TArray<string>;
  I: Integer;
  JsonObject: TJSONObject;
begin
  // 读取可用数据
  Data := AContext.Connection.IOHandler.ReadLnWait(-1, False);

  // 添加数据到缓冲区
  AMessageBuffer.AddData(Data);

  // 获取完整的JSON消息
  Messages := AMessageBuffer.GetCompleteMessages;

  // 解析每个完整的消息
  for I := Low(Messages) to High(Messages) do
  begin
    try
      JsonObject := TJSONObject.ParseJSONValue(Messages[I]) as TJSONObject;
      try
        Writeln('Received JSON message: ' + JsonObject.ToString);
        // 处理解析后的JSON对象
      finally
        JsonObject.Free;
      end;
    except
      on E: Exception do
        Writeln('Error parsing JSON message: ' + E.Message);
    end;
  end;
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
begin
  ReceiveJsonData(AContext, FMessageBuffer);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FMessageBuffer := TMessageBuffer.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FMessageBuffer.Free;
end;


完整代码解释
1. 发送端:
   - `SendJsonData` 函数负责将JSON对象转换为字符串,并在末尾添加换行符 `\n` 作为分隔符。
   - 这样可以确保每个JSON消息都是独立的,并且可以通过换行符进行分割。
2. 接收端:
   - 使用 `TMessageBuffer` 类来管理接收到的数据缓冲区。
   - `AddData` 方法用于将新接收到的数据添加到缓冲区中。
   - `GetCompleteMessages` 方法用于从缓冲区中提取完整的JSON消息。它会根据换行符分割缓冲区中的数据,并返回完整的JSON消息数组。
   - 在 `ReceiveJsonData` 函数中,首先读取可用的数据并将其添加到缓冲区中。
   - 然后调用 `GetCompleteMessages` 方法获取完整的JSON消息,并逐个解析这些消息。
   - 使用 `TJSONObject.ParseJSONValue` 方法将字符串解析为JSON对象,并处理解析后的JSON对象。
这种方法可以有效地处理多包数据的情况,确保每次接收到的是一个完整的JSON消息。请根据具体需求调整代码中的细节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蝈蝈(GuoGuo)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值