0

使用 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之后继续发送。

在此处输入图像描述

4

1 回答 1

2

返回 0时ReceiveBuf(),表示套接字已被对方断开。你没有处理那个条件,所以你不断循环,一次又一次地回到 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;
于 2013-03-13T21:44:12.487 回答