需要帮助发送文件与Indy

时间:2013-06-01 09:50:44

标签: delphi delphi-7 indy-9

  1. 我使用TIdTCPServer和TIdTCPClient,客户端和服务器都在100 mbps的同一本地网络上
  2. 需要发送最多2 MB的文件
  3. 我没有使用Indy和Socket编程的经验
  4. *在客户端向服务器发送请求之后,它会循环直到与服务器断开连接,该文件是使用客户端本身创建的,但是大小为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;
    

    谢谢大家。

1 个答案:

答案 0 :(得分:4)

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

您正在犯的其他错误:

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

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

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

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

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

  6. 更新:试试这个:

    服务器:

    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;