【问题标题】:Problem sending more then 2 lines at time一次发送超过 2 行的问题
【发布时间】:2011-04-20 19:37:21
【问题描述】:

我的套接字有问题。
如果我使用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'
为什么?
对不起我的英语!

【问题讨论】:

  • 我对Delphi的SendText方法不熟悉,但是我没有看到任何在文本中指定回车的地方。
  • 服务器收到一行而不是两行。

标签: delphi sockets delphi-7 winsock


【解决方案1】:

SendText 不发送 CRLF。如果您需要发送新行,则必须明确执行:

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

【讨论】:

  • 但如果我使用:如果 Command='FormX' 然后开始 Form.Left:=strtoint(Socket.ReceiveText);
  • @Robrok:那就不要这样使用它:var SL: TStringList;begin SL := TStringList.create; try SL.Text := Socket.ReceiveText; if SL.Count > 1 then begin Form.Left := StrToInt(SL[0]); Form.Top := StrToInt(SL[1]); end; finally SL.Free; end; 应该为你做,你可以根据需要扩展它。
  • 我正在使用这个例子 var Mess,Bind,FrmLeft:WideString;混乱:=Socket.ReceiveText;绑定:=复制(混乱,1,4);如果 Bind='LEFT' 然后开始 FrmLeft:=Copy(Mess,5,3); Form1.Left:=StrToInt(FrmLeft);结尾; --简单
【解决方案2】:

TClientSocketTServerSocket 实现 TCP/IP,这是一个没有消息边界概念的字节流(与 UDP 不同)。当您调用SendText() 时,它只是将字符串内容原样转储到套接字上。当您调用ReceiveText() 时,它会返回当前在套接字缓冲区中的任何内容。这就是您看到服务器收到“Line1Line2”的原因。如果要区分这两行,则需要在它们之间发送分隔符,例如 CRLF 序列,然后需要更新服务器代码以查找该分隔符。由于 TCP/IP 是字节流,因此写入和读取之间没有保证的一对一关系。举个例子,你写了 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;

【讨论】:

    【解决方案3】:

    您需要在 Edit1.Text 和 Edit2.Text 中添加 CRLF 或换行符

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多