使用indyTcp服务器和客户端发送和接收TStringStream [英] send and recive TStringStream with indyTcp server and client

查看:155
本文介绍了使用indyTcp服务器和客户端发送和接收TStringStream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Indy TCP组件将TStringStream从客户端发送到服务器,然后将其从服务器发送回客户端.

I am trying to send a TStringStream from client to server, then send it back from server to client, using Indy TCP components.

这是我的客户代码:

var
  Jpg: TJPEGImage;
  StringStream: TStringStream;
  strcams, StringImageData: String;
  byt, i: integer;

procedure SendCommandWithParams(Command, Params: String);
begin
  Lock;
  try
    if not FTCP.Connected then
    begin
      exit;
    end;
    FTCP.Socket.WriteLn('1' + Command, IndyTextEncoding_UTF8);
    FTCP.Socket.WriteLn(Params, IndyTextEncoding_UTF8);
  finally
    Unlock;
  end;
end;

begin
  Jpg := TJPEGImage.Create;
  StringStream := TStringStream.Create('');
  try
    try
      Jpg.Performance := jpBestSpeed;
      Jpg.ProgressiveEncoding := True;
      Jpg.ProgressiveDisplay := True;
      Jpg.Assign(Image2.Picture.Bitmap);
      Jpg.CompressionQuality := 25;
      Jpg.Compress;
      Jpg.SaveToStream(StringStream);
      StringImageData := StringStream.DataString;
      strcams := '<[S:' + IntToStr(Length(StringImageData)) + 'B]>' +
        StringImageData;
      if Length(strcams) < byt then
      begin
       SendCommandWithParams('SIMGSEND', strcams + sep + 'IMGID5423' + sep);
      end;
    except
      on e: exception do
        //
    end;
  finally
    StringImageData := '';
    FreeAndNil(Jpg);
    FreeAndNil(StringStream);
  end;
end;

我可以接收TStringStream数据,但是接收到的数据已损坏,有时它会被我发送的第二个参数'IMGID5423' + sep代替.我不确定这是否是由于通过TCP发送数据包的某些限制而导致数据无法到达完整,还是解析器问题?

I can receive the TStringStream data, but the data received is corrupted, and some times it gets replaced with the second parameter that I send which is 'IMGID5423' + sep. I am not sure if this is because of some limit of packet sending through TCP so the data does not arrive complete, or is this a parser issue?

我当前的解析器应该分隔每个以#13#10结尾的文本.这是它的外观:

My current parser should separate each text that ended with #13#10. Here is how it looks:

var
  ReceiveParams, ReceiveStream: Boolean;
  S: string;
  Command: String;
begin
  Command := Fholdcommand;
  ReceiveParams := false;
  ReceiveStream := false;

  if Command[1] = '1' then // command with params
  begin
    Command := Copy(Command, 2, MaxInt);
    ReceiveParams := True;
  end;

  if ReceiveParams then // params incomming
  begin
    S := FTCP.Socket.ReadLn(IndyTextEncoding_UTF8);
    FCMD := Command;
    FPRMS := S;
    FSTREAM := false;
    if Assigned(FOnCallbackProc) then
    begin
      Synchronize(DoCallbackProc);
    end;
  end;

我仍然对真正的问题感到困惑.我尝试在本地过程中发送TStringStream,并且正常接收到它而没有任何损坏.

I am still confused about the real issue. I try to send the TStringStream in a local procedure, and it is received normally without any corruption.

我是否完全通过Indy发送了错误的数据?

Am I sending the data wrong altogether through Indy?

这是我接收数据的方式:

This is how I am receiving the data:

procedure CreateJpg(Data:string);
var
  StringStream : TStringStream;
  JpegImage : TJPEGImage;
  Bitmap : TBitmap;
  tmpPos:integer;
  pp:string;
  label check;
begin
  GData := Data;

  if LeftStr(GData,4) = '<[S:' then 
  begin
    tmpPos := Pos(WideString('B]>'),GData);
    pp := Copy(GData,5,tmpPos-5);
    CDataELen :=  StrToInt(pp); //MidStr(st,5,tmppos - 5);
    CData := RightStr(GData,length(GData)-(tmppos+2));
    goto check;
  end;

  CData := CData + GData;

  check:

  //if CDataELen = length(CData) then
  begin
    StringStream := TStringStream.Create('');
    JpegImage := TJpegImage.Create;
    StringStream.WriteString(CData);
    CData := '';
    try
      try
        StringStream.Seek(0, soFromBeginning);
        JpegImage.LoadFromStream(StringStream);
        Bitmap := TBitmap.Create;
        with Bitmap do
        begin
          Canvas.Lock;
          try
            Width := JpegImage.Width;
            Height := JpegImage.Height;
            Canvas.Draw(0, 0, JpegImage);
          finally
            Canvas.Unlock;
          end;
        end;

        img.Picture.Bitmap.Width := Bitmap.Width;
        img.Picture.Bitmap.Height := Bitmap.Height;
        img.Picture.Bitmap.Canvas.Draw(0, 0, Bitmap);

      except
        on E: Exception do
          //
      end;
    finally
      FreeAndNil(StringStream);
      FreeAndNil(JpegImage);
      FreeAndNil(Bitmap);
    end;
  end;
end;

推荐答案

问题是您将JPG二进制数据保存到TStringStream,然后让其重新解释二进制数据,就像它是字符串数据.你不能那样做.您需要将JPG数据另存为二进制流(例如TMemoryStream),然后使用字符串安全编码(例如Base64)编码二进制数据.

The problem is that you are saving the JPG binary data to a TStringStream and then letting it reinterpret the binary data as if it were string data. You can't do that. You need to save the JPG data to a binary stream instead, like TMemoryStream, and then encode the binary data using a string-safe encoding, like Base64.

请尝试以下类似操作:

uses
  ..., IdCoder, IdCoderMIME;

...

var
  Jpg: TJPEGImage;
  JpegStream: TMemoryStream;
  strcams, StringImageData: String;
begin
  try
    JpegStream := TMemoryStream.Create;
    try
      Jpg := TJPEGImage.Create;
      try
        Jpg.Performance := jpBestSpeed;
        Jpg.ProgressiveEncoding := True;
        Jpg.ProgressiveDisplay := True;
        Jpg.Assign(Image2.Picture.Bitmap);
        Jpg.CompressionQuality := 25;
        Jpg.Compress;
        Jpg.SaveToStream(JpegStream);
      finally
        Jpg.Free;
      end;
      JpegStream.Position := 0;
      StringImageData := TIdEncoderMIME.EncodeStream(JpegStream);
    finally
      JpegStream.Free;
    end;
    strcams := '<[S:' + IntToStr(Length(StringImageData)) + 'B]>' + StringImageData;
    SendCommandWithParams('SIMGSEND', strcams + sep + 'IMGID5423' + sep);
  except
    on e: exception do
      //
  end;
end;

然后在接收端:

procedure CreateJpg(Data: string);
var
  JpegStream: TMemoryStream;
  JpegImage: TJPEGImage;
  Bitmap: TBitmap;
  tmpPos, tmpLen: integer;
  pp: string;
begin
  try
    if not TextStartsWith(Data, '<[S:') then
    begin
      // bad data, do something else...
      Exit;
    end;

    tmpPos := Pos('B]>', Data);
    pp := Copy(Data, 5, tmpPos-5);
    tmpLen := StrToInt(pp);
    Data := Copy(Data, tmpPos+3, tmpLen);

    Bitmap := TBitmap.Create;
    try
      JpegImage := TJpegImage.Create;
      try
        JpegStream := TMemoryStream.Create;
        try
          TIdDecoderMIME.DecodeStream(Data, JpegStream);
          JpegStream.Position := 0;
          JpegImage.LoadFromStream(JpegStream);
        finally
          JpegStream.Free;
        end;
        with Bitmap do
        begin
          Canvas.Lock;
          try
            Width := JpegImage.Width;
            Height := JpegImage.Height;
            Canvas.Draw(0, 0, JpegImage);
          finally
            Canvas.Unlock;
          end;
        end;
      finally
        JpegImage.Free;
      end;
      img.Picture.Assign(Bitmap);
    finally
      Bitmap.Free;
    end;        
  except
    on E: Exception do
      //
  end;
end;

这篇关于使用indyTcp服务器和客户端发送和接收TStringStream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆