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