0
  1. 我使用 TIdTCPServer 和 TIdTCPClient,客户端和服务器都在同一个本地网络上,速度为 100 mbps
  2. 需要发送最多 2 MB 的文件
  3. 我对 Indy 和 Socket 编程没有经验

*客户端向服务器发送请求后,循环直到与服务器断开连接,文件由客户端自己创建,但大小为0字节

IdTCPServer.OnExecute ...

begin
  CS.Enter;

  try
    InputString := AThread.Connection.ReadLn;

    if InputString = 'PIC' then begin
      AFullFileName := FFilePath + 'PIC01.jpg';
      if FileExists(AFullFileName) then begin
        AFileStream := TFileStream.Create(AFullFileName, fmOpenRead + fmShareDenyNone);

        AThread.Connection.OpenWriteBuffer;
        AThread.Connection.WriteStream(AFileStream);
        AThread.Connection.CloseWriteBuffer;

        FreeAndNil(AFileStream);
      end;

      AThread.Connection.Disconnect;
    end;
  except
    on E : Exception do
      ShowMessage(E.Message);
  end;

  CS.Leave;
end;

Client.OnButtonClick ...

begin
  with IdTCPClient do begin
    if Connected then Disconnect;
    Host := '127.0.0.1';
    Port := 2018;
    Connect;
    WriteLn('PIC');
    //different folder with server's folder
    if FileExists(FFilePath + 'PIC01.jpg') then
      DeleteFile(FFilePath + 'PIC01.jpg');
    AFileStream := TFileStream.Create(FFilePath + 'PIC01.jpg', fmCreate);
    while Connected do
      ReadStream(AFileStream, -1, true);
    FreeAndNil(AFileStream);
    Disconnect;
  end;
end;

谢谢大家。

4

1 回答 1

4

您犯了一个经典的新手错误,即 WriteStream() 和 ReadStream() 调用不匹配。默认情况下,WriteStream() 不发送流大小,但您传递给 ReadStream() 的参数值告诉它期望流大小。

您正在犯的其他错误:

  1. 您在循环中调用 ReadStream(),但没有在循环中调用 WriteStream()。

  2. 将整个 OnExecute 代码包装在关键部分中。不要那样做。

  3. 将整个 OnExecute 代码包装在一个 try/except 中,它会吞下所有异常。不要吞下 EIdException 派生的异常。TIdTCPServer 需要处理它们。

  4. 调用 ShowMessage()。它不是线程安全的。请改用 Windows.MessageBox()。

  5. 通过 WriteStream() 使用写缓冲。这对于大文件来说是一种巨大的内存浪费。摆脱它。

更新:试试这个:

服务器:

begin
  InputString := AThread.Connection.ReadLn;
  if InputString = 'PIC' then begin
    AFullFileName := FFilePath + 'PIC01.jpg';
    AFileStream := TFileStream.Create(AFullFileName, fmOpenRead or fmShareDenyNone);
    try
      AThread.Connection.WriteStream(AFileStream, True, True);
    finally
      AFileStream.Free;
    end;
  end;
  AThread.Connection.Disconnect;
end;

客户:

begin
  if IdTCPClient.Connected then IdTCPClient.Disconnect;
  IdTCPClient.Host := '127.0.0.1';
  IdTCPClient.Port := 2018;
  if FileExists(FFilePath + 'PIC01.jpg') then
    DeleteFile(FFilePath + 'PIC01.jpg');
  AFileStream := TFileStream.Create(FFilePath + 'PIC01.jpg', fmCreate);
  try
    try
      IdTCPClient.Connect;
      try
        IdTCPClient.WriteLn('PIC');
        IdTCPClient.ReadStream(AFileStream, -1, False);
      finally
        IdTCPClient.Disconnect;
      end;
    finally
      AFileStream.Free;
    end;
  except
    DeleteFile(FFilePath + 'PIC01.jpg');
  end;
end;
于 2013-06-01T18:25:50.057 回答