2016-09-12 2 views
-1

Я пытаюсь отправить TStringStream с клиента на сервер, а затем отправить его обратно с сервера на клиент, используя компоненты Indy TCP.отправлять и получать TStringStream с сервером и клиентом indyTcp

Вот мой код клиента:

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, поэтому данные не поступают полностью или это проблема парсера?

Мой текущий синтаксический анализатор должен отделять каждый текст, который закончился #13#10. Вот как это выглядит:

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 в локальную процедуру, и она получена нормально без какого-либо повреждения.

Я отправляю данные неправильно через Indy?

Это, как я получаю данные:

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; 
+0

Я вижу много кода, как это с обработчиком исключений, который проглатывает исключения. Почему ты бы так поступил? Не считаете ли вы, что важно реагировать на исключения, а не игнорировать их и надеяться, что ваша программа по-прежнему будет работать? –

+0

Я регистрирую исключения на диске, которые j juts помещают пустой комментарий там, потому что он не был определен –

+0

. Ваша правая версия исказила вопрос. Я вернул его. –

ответ

2

Проблема заключается в том, что вы сохраняете двоичные данные JPG на TStringStream, а затем даете reinterpret двоичные данные, как если бы это были строковые данные. Вы не можете этого сделать. Вам нужно сохранить данные JPG в бинарный поток, например TMemoryStream, а затем кодировать двоичные данные с использованием строковой кодировки, такой как 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; 
+0

Я не должен кодировать 'strcams'? Я использовал ваш код для кодировки base64 здесь http://stackoverflow.com/questions/22026825/base64-encode-and-decode-is-not-working Я использовал 'ByteEncoding', я попытался отправить то же, что и вы, но изображения пустые я обновлю вопрос с кодом получения –

+0

Вам не нужно, чтобы base64 кодировал 'strcams' сам (вы * можете *, если хотите, но вы не нуждаетесь * в). Весь ваш протокол основан на строках, а 'strcams' содержит только символы ASCII, не требуется специальной кодировки. Что касается более раннего кода, с которым вы связались, он предназначался для кодировки base64 ** строковых данных ** (путем преобразования строковых символов в кодированные кодировкой байтов, а затем для кодирования этих байтов base64). JPG - ** двоичные данные **. Используйте 'EncodeStream()' вместо 'EncodeString()', если вы хотите кодировать двоичные данные ** base64 **. –

+0

ok Я попробую, если я расшифрую этот кодированный поток? я имею в виду, что я был декодирован 'strcams' после его получения на сервере –

1

Ваша проблема, как представляется, что вы лечите двоичные данные, как будто это текст. Двоичные данные могут содержать все, например, #13#10 разрывы строк или вообще что-либо.

Если вы хотите отправить эти данные в виде текста, вам необходимо использовать текстовую кодировку. Например, закодируйте его как base64.

Или передайте контент как двоичный, а не текстовый.

+0

Я попытался использовать base64 для кодирования двоичных данных. я получил изображение пустым –

+0

Тогда вы сделали что-то не так. Не ожидайте от нас отладки вашего будущего кода. –

+0

Я попытался сравнить текст с посылкой и получил тот, который они разные. Думаю, я получил проблему с кодировкой –

Смежные вопросы