procedure TFileServerThread.Execute;
  Var
  SocketStream: TWinSocketStream;
  RecvData:String;
  RecvLen:Integer;
Begin  While Not Terminated And ClientSocket.Connected Do
  Try
    SocketStream := TWinSocketStream.Create(ClientSocket, 60000);
    Try
      RecvData:='';
      SetLength(RecvData,MaxDataLen);
      RecvLen:=SocketStream.Read(RecvData[1],MaxDatalen);
      if RecvLen = 0 Then
      Begin
        ClientSocket.SendText('Timeout on Server'+#13#10);
        sleep(1);
        ClientSocket.Close;
        Terminate;
      End;
      If ClientSocket.Connected Then
      begin
          Delete(RecvData,RecvLen+1,MaxDataLen-RecvLen);
          //问题就是有时候正常,有时不正常,比如上一个包收到的数据包含了下一个包的一部分,下一个包收到了又不是完整的!而我发送的时候绝对是一个一个发的!有时候收到的数据前面的几个字节会跑到最后面,为这个问题烦恼了一个星期,忘高手赐教!!!!万分感谢!!!
       end;
    Finally
      SocketStream.Free;
    End;
  Except
    HandleException;
  End;
end;

解决方案 »

  1.   

    RecvData
    别用string
    自己定义record 类型
    记得定义的时候加上packed Record
      

  2.   

    这是你对TCP/IP通讯的理解有问题。不可能也没有办法,让每一次的发送和一次接受来一一对应。你发送了几次数据,而接收端去一次收完(这个描述不准确,但是按照你的意思你该能理解)正确的做法是把接收看作一个流,是连续的数据,和发送的次数没关系,自己定义的数据的起始和终止标识(比如用回车),来识别你的一个完整数据。
    你不要把触发的一次接收事件来判断,而是来判断回车的位置。
      

  3.   

    这是你对TCP/IP通讯的理解有问题。按照TClientSocket和TServerSocket控件来说(Indy的也这样),
    不可能也没有办法,让每一次的发送和一次接受来一一对应。比如你发送了几次数据,而接收端可能一次收完(这个描述不准确,但是按照你的意思你该能理解)正确的做法是把接收看作一个流,是连续的数据,和发送的次数没关系,自己定义的数据的起始和终止标识(比如用回车),来识别你的一个完整数据。
    你不要把触发的一次接收事件来作为判断一次通讯的依据,而是来标识来判断。
    比如用回车来表示每次发送的完成,
    接收端收到数据后应该判断回车的位置,如果有,则把回车前的作为一个通讯的数据,余下的是另一个记录的一部分;
    如果没有回车,说明当前接收的不完整,还要等待其余数据到来。