Delphi idtcpserver idtcpclient tstringstream в строку

Я пытаюсь отправить строку из tidtcpserver в tidtcpclient в Delphi, но когда я отправляю строку, клиент ничего не получает. Я не получаю никаких ошибок. Я использую tstringstream, потому что я хочу отправить строку base64 (writeln/readln не может отправить / получить столько текста) Это код отправки в idtcpserver1:

procedure TForm1.sendtext(index:integer; txt:string);
var
  StrStream:tStream;
  List: TList;
  AContext: TIdContext;
begin
  txt := trim(txt);
  strstream := TMemoryStream.Create;
  strstream.Write(PAnsiChar(txt)^, Length(txt));
  strstream.Position := 0;
  List := idTcpServer1.Contexts.LockList;
  AContext := TIdContext(List[index]);
  AContext.Connection.IOHandler.write(StrStream);
  idTcpServer1.Contexts.UnLockList;
end;

Это код чтения в idtcpclient1

procedure TIndyClient.Execute;
var
StrStream:tStringStream;
receivedtext:string;
begin
StrStream := tstringstream.Create;
form1.IdTCPClient1.IOHandler.readstream(StrStream);
receivedtext := strstream.DataString;
if receivedtext = '' = false then
begin
  showmessage(receivedtext);
end;
end;

Кто-нибудь знает, что я делаю не так?

1 ответ

Решение

Вы делаете очень распространенную ошибку новичка несоответствия IOHandler.Write(TStream) а также IOHandler.ReadStream() звонки. По умолчанию, ReadStream() ожидает, что данным потока предшествует размер потока, но Write(TStream) не отправляет размер потока по умолчанию.

Попробуйте это вместо этого:

procedure TForm1.sendtext(index: integer; const txt: string);
var
  StrStream: TMemoryStream;
  List: TList;
  AContext: TIdContext;
begin
  strStream := TMemoryStream.Create;
  try
    WriteStringToStream(StrStream, Trim(txt), enUTF8);
    List := idTcpServer1.Contexts.LockList;
    try
      AContext := TIdContext(List[index]);
      AContext.Connection.IOHandler.Write(StrStream, 0, True);
    finally
      idTcpServer1.Contexts.UnlockList;
    end;
  finally
    StrStream.Free;
  end;
end;

procedure TIndyClient.Execute;
var
  StrStream: TMemoryStream;
  receivedtext: string;
begin
  StrStream := TMemoryStream.Create;
  try
    Form1.IdTCPClient1.IOHandler.ReadStream(StrStream, -1, False);
    StrStream.Position := 0;
    receivedtext := ReadStringFromStream(StrStream, enUTF8);
  finally
    StrStream.Free;
  end;
  if receivedtext <> '' then
  begin
    // ShowMessage() is not thread-safe...
    MessageBox(0, PChar(receivedtext), PChar(Application.Title), MB_OK);
  end;
end;

В качестве альтернативы, поскольку размер потока теперь отправляется, принимающий код может использовать ReadString() вместо ReadStream():

procedure TIndyClient.Execute;
var
  receivedtext: string;
begin
  with Form1.IdTCPClient1.IOHandler do
  begin
    // you can alternatively set the IOHandler.DefStringEncoding
    // instead of passing the encoding as a parameter...
    receivedtext := ReadString(ReadLongInt, enUTF8);
  end;
  if receivedtext <> '' then
  begin
    // ShowMessage() is not thread-safe...
    MessageBox(0, PChar(receivedtext), PChar(Application.Title), MB_OK);
  end;
end;

КСТАТИ, WriteLn()/ReadLn() не имеют никаких ограничений по длине, они могут обрабатывать большие строки, пока есть доступная память (и в отправляемом тексте нет разрывов строк). Вы, вероятно, смущены ReadLn() быть предметом IOHandler.MaxLineLength, который по умолчанию установлен на 16K символов, но вы можете обойти это:

procedure TForm1.sendtext(index: integer; const txt: string);
va
  List: TList;
  AContext: TIdContext;
begin
  List := idTcpServer1.Contexts.LockList;
  try
    AContext := TIdContext(List[index]);
    // you can alternatively set the IOHandler.DefStringEncoding
    // instead of passing the encoding as a parameter...
    AContext.Connection.IOHandler.WriteLn(Trim(txt), enUTF8);
  finally
    idTcpServer1.Contexts.UnlockList;
  end;
end;

procedure TIndyClient.Execute;
var
  receivedtext: string;
begin
  // you can alternatively set the IOHandler.DefStringEncoding
  // and IOHandler.MaxLineLength instead of passing them as parameters...
  receivedtext := Form1.IdTCPClient1.IOHandler.ReadLn(LF, -1, MaxInt, enUTF8);
  if receivedtext <> '' then
  begin
    // ShowMessage() is not thread-safe...
    MessageBox(0, PChar(receivedtext), PChar(Application.Title), MB_OK);
  end;
end;
Другие вопросы по тегам