我一直从TClientSocket接收0字节

时间:2013-03-13 20:36:52

标签: delphi sockets winsock

使用DbgView,我看到收到Stream后,服务器接收0字节超过100次,这是什么?这对我来说是新的,我从来没有看到过这种情况。

我个人认为这是客户端问题,可以吗?

这就是我收到流服务器端的方式

  FMemStream := Socket.ReceiveStream(FMemStreamSize, cbUpdateStreamProgBar);
    try
      doClientReadStreamEnd;
    finally
      FMemStream.Free;
      FInStreamMode := False; // we're not in stream mode anymore
    end;

function TCustomWinSocketHelpher.ReceiveStream(StreamLen: Integer; Callback: TUpdateProgBarProc): TMemoryStream;
const
  ChunkSize = 4096; // 4kb
var
  PData: PByte;
  ReadAmount: Integer;
begin
  Result := TMemoryStream.Create;
  GetMem(PData, StreamLen);
  try
    while StreamLen > 0 do
    begin
      ReadAmount := ReceiveBuf(PData^, ChunkSize);
      if (ReadAmount > 0) then
      begin
        Result.Write(PData^, ReadAmount);
        Callback(ReadAmount); // update gui
        Inc(PData^, ReadAmount); // update PData current position
        Dec(StreamLen, ReadAmount); // update loop condition
      end;
    end;
  finally
    FreeMem(PData);
  end;
end;
在客户端

,这就是我发送流的方式

FClientSocket.Socket.SendStreamEx(RemoteProcedureCalls.Stream);

procedure TCustomWinSocketHelpher.SendStreamEx(Stream: TStream);
begin
  Stream.Seek(0, TSeekOrigin.soBeginning);
  SendStream(Stream);
end;

以下是其外观的照片,不应在 5 之后继续发送。

enter image description here

1 个答案:

答案 0 :(得分:2)

ReceiveBuf()返回0时,表示套接字已被另一方断开连接。你没有处理这个条件,所以你继续循环,一次又一次地回到0。任何小于1的值都是读取失败,需要这样处理。如果ReceiveBuf()返回-1,则发生实际读取错误,但只有在错误为WSAEWOULDBLOCK时才会返回该结果,这不是致命错误,或者您已分配OnError个事件处理程序这是设置ErrorCode := 0。否则,ReceiveBuf()会在实际套接字错误上引发ESocketError异常。

试试这个:

function TCustomWinSocketHelpher.ReceiveStream(StreamLen: Integer; Callback: TUpdateProgBarProc): TMemoryStream;
const
  ChunkSize = 4096; // 4kb
var
  PData: PByte;
  ReadAmount: Integer;
begin
  Result := TMemoryStream.Create;
  try
    GetMem(PData, ChunkSize);
    try
      while StreamLen > 0 do
      begin
        ReadAmount := ReceiveBuf(PData^, Min(ChunkSize, StreamLen));
        if ReadAmount < 0 then
        begin
          if WSAGetLastError() = WSAEWOULDBLOCK then
            Continue;
          // an OnError event handler must have disabled an exception being raised
          Exit;
        end;
        if ReadAmount = 0 then
        begin
          // socket disconnected
          raise Exception.Create(''); // or just Exit if you don't mind that the expected data is incomplete
        end;
        Result.WriteBuffer(PData^, ReadAmount);
        Callback(ReadAmount); // update gui
        Dec(StreamLen, ReadAmount); // update loop condition
      end;
    finally
      FreeMem(PData);
    end;
  except
    Result.Free;
    raise;
  end;
end;