2011-03-31 66 views
1

我正在寫一個ftp客戶端來上傳文件。僞代碼是類似於下面的東西vC++ - 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上傳一個文件時,通過lan(他的機器是ubuntu),上傳速度爲10MB/s。我無法理解這背後的邏輯。

注意:我使用FileZilla FTP服務器,它能夠顯示客戶端文件的上傳/到達速度。

回答

0
  1. 我建議使用內存映射I/O
  2. 如果你想使用ReadFile API函數,不要被1000個字節讀取。

    2.1讀2 ^千字節(1024,2048,4096,等...)

    2.2閱讀每個迭代超過1024個字節(對於大文件太小)。嘗試將其增加到4MB或類似的東西。你可以做這個不變的文件大小依賴。

    2.3當前一個塊通過send發送時,可以使用異步I/O從文件讀取下一個塊。

嗯......可能是別人可以提示更多。

+0

你是否認爲ReadFile正在減慢這個過程?至於我所關心的,系統調用是最快的函數調用。 – prabhakaran 2011-03-31 06:54:28

+0

實際上不是'ReadFile',而是您使用它的方式:不讀取666或1231字節。它真的很慢。讀取2^k字節。而對於大文件來說,通過大小爲1024字節的塊讀取1GB需要1 048 576次迭代。你應該增加緩衝區的大小。 – maverik 2011-03-31 07:12:06

1

發佈僞代碼可能會隱藏重要的性能問題。所以目前還不清楚你如何填充變量buf。

但是你不應該發送1000字節的塊。這可以使TCP在服務器端更經常地發送ACK。

+0

代碼有點模糊,所以我張貼關鍵線 – prabhakaran 2011-03-31 06:37:30

1

你的僞碼遺漏了一些重要的細節,但我會採取一些猜測補償:-)

  • 請嘗試將插座非阻塞,使用select()你什麼時候知道的可以寫入和,而你的插座發送寫了不到64千
  • 塊(也就是現在的異步),您可以讀取該文件

你的僞代碼,現在成爲下一大塊:

{ 
    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 // 
    } 
} 

使得套接字非阻塞允許您的代碼在套接字impl後立即返回。知道該怎麼做,所以你不必等待,只要它做你需要做的事情 - 這意味着你可以從文件讀取,而發送數據。

+0

現在我把套接字放在非阻塞模式,仍然是緩慢的。但據我所知阻塞/非阻塞不能被視爲異步I/O 。非阻塞意味着套接字發現沒有進一步發送/接收,然後完成send()/ recv()。 – prabhakaran 2011-03-31 07:05:07

+0

對於寫入非阻塞套接字,數據被複制到套接字的緩衝區中,並從那裏異步處理。對於從非阻塞套接字讀取,你是對的:這意味着如果沒有什麼可讀的話,它會簡單地返回(即產生一個「阻塞」錯誤)。我的建議的想法是確保你的套接字impl。始終有數據要發送。 – rlc 2011-03-31 07:24:43

+0

如果只是讓套接字非阻塞沒有幫助,你能告訴我你的客戶端代碼在哪裏花費時間嗎?例如。測量它在循環的每個部分花費的時間。 – rlc 2011-03-31 07:27:06