Проблема при отправке более 2 строк одновременно - PullRequest
2 голосов
/ 20 апреля 2011

У меня проблема с розетками.
Если я отправлю более двух строк текста, используя TClientSocket, то сервер получит одну строку вместо двух.

Клиентская часть:

ClientSocket1.Socket.SendText(Edit1.Text);//Text is 'Line1'
ClientSocket1.Socket.SendText(Edit2.Text);//Text is 'Line2'  

Серверная часть:

var
s: String;
begin
s := Socket.ReceiveText;
Memo1.Lines.Add(S);

Memo1 созданная строка 'Line1Line2'
Почему?
Извините за мой английский!

Ответы [ 3 ]

5 голосов
/ 20 апреля 2011

SendText не отправляет CRLF.Если вам нужно отправить новую строку, вам придется сделать это явно:

ClientSocket1.Socket.SendText(Edit1.Text + #13#10);
ClientSocket1.Socket.SendText(Edit2.Text + #13#10);
4 голосов
/ 21 апреля 2011

TClientSocket и TServerSocket реализуют TCP / IP, который является потоком байтов, который не имеет понятия границ сообщения (в отличие от UDP, который это делает). Когда вы вызываете SendText(), он просто выгружает содержимое String как есть в сокет. Когда вы вызываете ReceiveText(), он возвращает то, что в данный момент находится в буфере сокета. Вот почему вы видите, что сервер получает 'Line1Line2'. Если вы хотите провести различие между двумя строками, вам необходимо отправить разделитель между ними, например, последовательность CRLF, а затем необходимо обновить код вашего сервера, чтобы найти это. Поскольку TCP / IP является байтовым потоком, между записью и чтением не существует гарантированного отношения 1: 1. Например, вы записали 5 байтов, за которыми следуют 5 байтов, но сервер получил сразу 10 байтов. Таким образом, ваш код чтения должен буферизовать все, что он получает, и тогда вы можете проверить буфер для данных, которые вы ищете, например:

Клиент:

ClientSocket1.Socket.SendText(Edit1.Text + #13#10);
ClientSocket1.Socket.SendText(Edit2.Text + #13#10);

Сервер:

procedure TForm1.ServerSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
begin
  Socket.Data := TMemoryStream.Create;
end;

procedure TForm1.ServerSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  TMemoryStream(Socket.Data).Free;
  Socket.Data := nil;
end;

procedure TForm1.ServerSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
  Strm: TMemoryStream;
  RecvLen: Integer;
  StrmSize, I: Int64;
  Ptr: PByte;
  B: Byte;
  s: AnsiString;
begin
  Strm := TMemoryStream(Socket.Data);

  RecvLen := Socket.ReceiveLength;
  if RecvLen <= 0 then Exit;

  StrmSize := Strm.Size;
  Strm.Size := StrmSize + RecvLen;

  Ptr := PByte(Strm.Memory);
  Inc(Ptr, Strm.Position);

  RecvLen := Socket.ReceiveBuf(Ptr^, RecvLen);
  if RecvLen <= 0 then
  begin
    Strm.Size := StrmSize;
    Exit;
  end;

  Strm.Size := StrmSize + RecvLen;

  while (Strm.Size - Strm.Position) >= 2 do
  begin
    Strm.ReadBuffer(B, 1);
    if B <> 13 then Continue;

    Strm.ReadBuffer(B, 1);
    if B <> 10 then
    begin
      if B = 13 then
      begin
        Strm.Seek(-1, soCurrent);
        Continue;
      end;
    end;

    SetString(s, PAnsiChar(Strm.Memory), Strm.Position-2);

    StrmSize := Strm.Size - Strm.Position;
    if StrmSize then
    begin
      Strm.Clear;
    end else
    begin
      Ptr := PByte(Strm.Memory);
      Inc(Ptr, Strm.Position);
      Move(Ptr^, Strm.Memory^, StrmSize);
      Strm.Size := StrmSize;
      Strm.Position := 0;
    end;

    Memo1.Lines.Add(S);
  end;
 end;
1 голос
/ 20 апреля 2011

Вам необходимо добавить CRLF или символ новой строки в Edit1.Text и Edit2.Text

...