【问题标题】:vc++ - Ftp client code - uploading a file is very slowvc++ - Ftp 客户端代码 - 上传文件很慢
【发布时间】:2011-03-31 05:53:45
【问题描述】:

我正在编写一个 ftp 客户端来上传文件。伪代码如下所示

{

    command_Socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    login...//

    pass.. // passive mode

    get the address from the reply ... // 

    data_Socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    connect the data_Socket to that address ..//

    open the file using createFile(....) //

    loop
    {
        char buf[1000];

        readFile and fill the buf //

        send(dataSocket,buf,..);
    }

}

现在,问题是上传速度是 20 kB/s,即使我在同一台机器上上传文件。但是当一个人使用ftp上传一个文件时,通过局域网(他的机器是ubuntu),上传速度是10MB/s。我无法理解这背后的逻辑。

注意:我使用的是 FileZilla FTP 服务器,它可以显示客户端文件的上传/到达速度。

【问题讨论】:

    标签: c++ winapi visual-c++ ftp logic


    【解决方案1】:

    发布伪代码可能会隐藏重要的性能问题。所以不清楚如何填充变量buf。

    但您不应该发送 1000 字节的块。这可能会导致 TCP 在服务器端发送 ACK 的频率高于必要的频率。

    【讨论】:

      【解决方案2】:

      你的伪代码遗漏了一些重要的细节,但我会做一些猜测来弥补:-)

      • 尝试使您的套接字成为非阻塞的,使用 select() 来了解您何时可以写入它并写入 64 K 以下的块
      • 当您的套接字正在发送时(现在是异步的),您可以读取文件的下一个块

      您的伪代码现在变为:

      {
         command_Socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
          login...//
          pass.. // passive mode
          get the address from the reply ... // 
          data_Socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
          /* set data socket to non-blocking  */
          connect the data_Socket to that address ..//
          open the file using createFile(....) //
          /* read a chunk */
          loop
          {
              select
              send data
              readFile and fill the buf //
          }
      }
      

      使套接字非阻塞允许您的代码在套接字实现时立即返回。知道该做什么,因此您无需等待它执行您需要它执行的操作 - 这意味着您可以在发送数据的同时读取文件。

      【讨论】:

      • 现在我将套接字置于非阻塞模式,仍然很慢。但据我所知,阻塞/非阻塞不能被视为异步 i/o。非阻塞意味着当套接字发现没有进一步的发送/接收然后完成发送()/接收()。
      • 对于非阻塞套接字的写入,数据被复制到套接字的缓冲区并从那里异步处理。对于从非阻塞套接字读取,您是对的:这意味着如果没有可读取的内容(即生成“将阻塞”错误),它将简单地返回。我建议的想法是确保您的套接字实现。总是有数据要发送。
      • 如果只是使套接字非阻塞并没有帮助,你能告诉我你的客户端代码把时间花在了哪里吗?例如。测量它在循环的每个部分花费的时间。
      • 您可以尝试的另一件事是通过将 TCP_NODELAY 设置为套接字选项来停用 Nagle 算法。如果这有帮助,这基本上意味着你的块大小仍然太小,所以你应该增加它。当你完成实验后,Nagle 应该真的回来了..
      【解决方案3】:
      1. 我建议使用内存映射 I/O
      2. 如果要使用ReadFile API 函数,请不要按 1000 字节读取。

        2.1 读取 2^k 字节(1024、2048、4096 等...)

        2.2 每次迭代读取超过 1024 字节(对于大文件来说太小了)。尝试将其增加到 4MB 或类似的东西。您可以根据文件大小执行此常量。

        2.3 当前一个块通过send 发送时,您可以使用异步 I/O 从文件中读取下一个块。

      嗯...可能其他人可以提出更多建议。

      【讨论】:

      • 您认为 ReadFile 会减慢进程吗?至于我所关心的,系统调用是最快的函数调用。
      • 实际上不是ReadFile,而是你使用它的方式:不要读取 666 或 1231 字节。它真的很慢。读取 2^k 字节。对于大文件,说 1GB 的大小为 1024 字节的块读取需要 1 048 576 次迭代。您可能应该增加缓冲区的大小。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      • 2012-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-07
      相关资源
      最近更新 更多