我正在尝试使用发送文件 TServerSocket/TClientSocket. 。只要我不在任何地方释放文件流,文件就会完全发送 form.OnCreate 事件也。如果我在任何地方免费提供,则只会发送 1% 或 2%。

我还必须把 TFileStream.Create 服务器端的一行代码 OnCreate 事件。如果我在中创建一个流 TForm2.ServerSocket1ClientRead 然后我得到一个 EFcreateerror: :“该进程无法访问文件,因为该文件正在被另一个进程使用”。

procedure TForm2.FormCreate(Sender: TObject);
begin
    FStream := TFileStream.Create('c:\temp\log.txt', fmCreate or
    fmShareDenyWrite);
end;

procedure TForm2.ClientSocket1Connect(Sender: TObject;
    Socket: TCustomWinSocket);
var
  fs: TFileStream;

begin
    fs := TFileStream.Create('c:\log.txt', fmOpenRead);
    socket.SendStream(fs);
end;

procedure TForm2.ServerSocket1ClientRead(Sender: TObject;
    Socket: TCustomWinSocket);
var
    iLen: Integer;
    Bfr: Pointer;
begin
    iLen := Socket.ReceiveLength;
    GetMem(Bfr, iLen);
    Socket.ReceiveBuf(Bfr^, iLen);
    FStream.Write(Bfr^, iLen);
    FreeMem(bfr);
    //fstream.free
end;

即使我这样写代码:

if fstream.Size = fstream.position then
    fstream.free

即使那样它也给我带来了问题。

这是什么奇怪的现象呢?这是Delphi的一个bug吗?如果是,有工作吗?如果重要的话:我使用的是德尔福2010。

更新: :抱歉,我的意思是如果我这样写代码:

if fileSize = fstream.position then
    fstream.free

抱歉,没有 fstream.sizefilesize. 。我已经将文件大小初始化为 300000(要接收的文件大小)。

解决了: 通过更换解决

FStream := TFileStream.Create('c:\temp\log.txt',
                              fmCreate or fmShareDenyWrite);

if not FileExists('c:\temp\log.txt') then
    FStream := TFileStream.Create('c:\temp\log.txt',
                                  fmCreate or fmShareDenyWrite);
有帮助吗?

解决方案

你正试图释放你的 FStream 一旦收到第一个数据块,就立即对象。不要那样做。该块通常小于整个文件,特别是当您发送大文件时。另外,检查 Position = Size 在接收端也是无用的,因为它总是会评估 true 自当前 Position 将始终位于流的末尾。正如我已经告诉过你的 其他讨论, ,您没有有效地使用 SendStream() 和 ReceiveBuf() 方法,并且发送方需要在发送文件数据之前发送文件大小(或者在文件末尾断开连接),以便接收方确切知道何时停止其阅读。

编辑:尝试这样的事情:

type
  TSocketBuffer = class
  public
    Stream: TStream;
    ExpectedSize: Int64;
    Data: array[0..1023] of Byte;
    DataOffset, DataSize: Integer;
    destructor Destroy; override;
  end;

  TServerSocketBuffer = class(TSocketBuffer)
  public
    FileName: String;
    destructor Destroy; override;
  end;

destructor TSocketBuffer.Destroy;
begin
  if Stream <> nil then Stream.Free;
  inherited;
end;

destructor TServerSocketBuffer.Destroy;
begin
  if Stream <> nil then FreeAndNil(Stream);
  if FileName <> '' then DeleteFile(FileName);
  inherited;
end;

procedure TForm2.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); 
var
  Buffer: TSocketBuffer;
begin 
  Buffer := TSocketBuffer.Create;
  Socket.Data := Buffer;

  // open the file to send...
  Buffer.Stream := TFileStream.Create('c:\log.txt', fmOpenRead or fmShareDenyWrite); 
  Buffer.ExpectedSize := Buffer.Stream.Size;

  // buffer the stream size...
  Move(Buffer.Data[0], Buffer.ExpectedSize, Sizeof(Int64));
  Buffer.DataOffset := 0;
  Buffer.DataSize := SizeOf(Int64);

  // begin sending...
  ClientSocket1Write(Sender, Socket);
end; 

procedure TForm2.ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket); 
begin 
  TSocketBuffer(Socket.Data).Free;
end; 

procedure TForm2.ClientSocket1Write(Sender: TObject; Socket: TCustomWinSocket); 
var
  Buffer: TSocketBuffer;
  NumBytes: Integer;
begin 
  // in case OnWrite is fired before OnConnect...
  if Socket.Data = nil then Exit;

  Buffer := TSocketBuffer(Socket.Data);
  if Buffer.Stream = nil then Exit;

  // keep sending until EOF is reached, or until the socket blocks/errors...
  repeat
    // if there is pending data buffered, send it now...
    while Buffer.DataOffset < Buffer.DataSize do
    begin
      NumBytes := Socket.SendBuf(Buffer.Data[Buffer.DataOffset], Buffer.DataSize-Buffer.DataOffset);
      if NumBytes <= 0 then Exit; // wait for next event...
      Inc(Buffer.DataOffset, NumBytes);
    end;

    // has EOF been reached?
    if Buffer.ExpectedSize <= 0 then Break;

    // read the next block of data from the stream...
    Buffer.DataOffset := 0;
    Buffer.DataSize := 0;
    NumBytes := Buffer.Stream.Read(Buffer.Data[0], Min(Buffer.ExpectedSize, SizeOf(Buffer.Data)));
    if NumBytes <= 0 then Break; // stream error, stop sending...
    Buffer.DataSize := NumBytes;
    Dec(Buffer.ExpectedSize, NumBytes);

    // the next loop iteration will start sending it...
  until False;

  // all done...
  FreeAndNil(Buffer.Stream);
  Socket.Close;
end; 

procedure TForm2.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket); 
begin
  Socket.Data := TServerSocketBuffer.Create;
end;

procedure TForm2.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket); 
begin
  TServerSocketBuffer(Socket.Data).Free;
end;

procedure TForm2.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); 
var 
  Buffer: TServerSocketBuffer;
  FileName: String;
  NumBytes: Integer; 
begin 
  Buffer := TServerSocketBuffer(Socket.Data);

  if Buffer.Stream = nil then
  begin
    // keep reading until stream size has been received in full...

    while Buffer.DataSize < SizeOf(Int64) do
    begin
      NumBytes := Socket.ReceiveBuf(Buffer.Data[Buffer.DataOffset], SizeOf(Int64)-Buffer.DataOffset);
      if NumBytes <= 0 then Exit; // wait for next event...
      Inc(Buffer.DataSize, NumBytes);
      Inc(Buffer.DataOffset, NumBytes);
    end;

    Move(Buffer.ExpectedSize, Buffer.Data[0], SizeOf(Int64));

    // create the file to store in...
    FileName := 'c:\temp\log.txt';
    Buffer.Stream := TFileStream.Create(FileName, fmCreate);
    Buffer.FileName := FileName;

    // (optional) pre-size the file...
    Buffer.Stream.Size := Buffer.ExpectedSize;
  end;

  // keep reading until EOF is reached, or until the socket blocks/errors...
  while Buffer.ExpectedSize > 0 do
  begin
    // read the next block of data from the socket...
    Buffer.DataOffset := 0;
    Buffer.DataSize := 0;

    NumBytes := Socket.ReceiveBuf(Buffer.Data[0], Min(Buffer.ExpectedSize, SizeOf(Buffer.Data)));
    if NumBytes <= 0 then Exit; // wait for next event...

    Buffer.DataSize := NumBytes;

    // save the data to the stream....
    repeat
      NumBytes := Buffer.Stream.Write(Buffer.Data[Buffer.DataOffset], Buffer.DataSize-Buffer.DataOffset); 
      if NumBytes <= 0 then
        // stream error, stop reading...
        Socket.Close;
        Exit;
      end;
      Inc(Buffer.DataOffset, NumBytes);
      Dec(Buffer.ExpectedSize, NumBytes);
    until Buffer.DataOffset >= Buffer.DataSize;
  end;

  // all done...
  FreeAndNil(Buffer.Stream);
  Buffer.FileName := '';
end; 
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top