Delphi idtcpserver idtcpclient tstringstream to string

时间:2015-01-03 20:06:24

标签: delphi indy tstream

我尝试将一个字符串从tidtcpserver发送到Delphi中的tidtcpclient,但是当我发送一个字符串时,客户端什么都没有收到。我没有得到任何错误。我正在使用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 个答案:

答案 0 :(得分:3)

您正在犯一个非常常见的新手错误,即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;

BTW,WriteLn()/ReadLn()没有任何长度限制,只要有可用内存,它们就可以处理大字符串(并且发送的文本中没有任何换行符)。你可能会因为ReadLn()受到IOHandler.MaxLineLength的限制而感到困惑,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; 默认设置为16K字符,但你可以绕过它:

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;

{{1}}