FILE *fp = fopen(FILENAME,"wb"); while((len = recv(sockfd, buff, sizeof(buff), 0)) > 0) |
fd = open(FILENAME, O_RDONLY); while((len =read(fd, buff, sizeof(buff))) >0) { send(sockfd, buff, len ,0); } close(fd); |
由于我磁盤分區時指定的塊大小為4096,為了最優讀取磁盤數據,buff大小設為4096字節.但在測試中發現設為1024或8192不會對傳輸速度帶來影響.
文件大小:9M; 耗時:0.71 - 0.76秒;
文件大小:32M; 耗時:2.64 - 2.68秒;
文件大小:64M; 耗時:5.36 - 5.43秒;
B. 使用sendfile()傳輸代碼段.
off_t offset = 0; fd = open(FILENAME, O_RDONLY); |
文件大小:9M; 耗時:0.71 - 1.08秒;
文件大小:32M; 耗時:2.66 - 2.74秒;
文件大小:64M; 耗時:5.43 - 6.64秒;
似乎還略有下降.根據sendfile的man手冊,我在使用該函數前調用了
int no = 1; |
文件大小:9M; 耗時:0.72 - 0.75秒;
文件大小:32M; 耗時:2.66 - 2.68秒;
文件大小:64M; 耗時:5.38 - 5.60秒;
這樣似乎達到了傳統方式的速度?!不管哪種環境下,我用ethereal抓包顯示每一個tcp包的playload部分最大也通常是1448字節.
看來我的測試沒有體現出"應用層數據的兩次拷貝帶來很大的消耗"這一說法.如果按照存在就是有理的說法的話,那我想sendfile()在兩種情況下才體現優勢,但我卻沒有環境測試:
1. 大并發量的文件服務器或HTTP服務器;
2. 內存資源緊張的嵌入式系統;
另外,網絡上大量的關于tcp選項中的TCP_CORK描述已經過時.在man手冊中早已提到該參數可以與TCP_NODELAY結合使用了.只是,只要設置了TCP_NODELAY選項后,不管是否設置TCP_CORK,包都會立即發出.
----------------------------------------------------------------------
補充:
TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,Nagle化在這里的含義是采用Nagle算法把較小的包組裝為更大的幀。 John Nagle是Nagle算法的發明人,后者就是用他的名字來命名的,他在1984年首次用這種方法來嘗試解決福特汽車公司的網絡擁塞問題(欲了解詳情請參看IETF RFC 896)。他解決的問題就是所謂的silly window syndrome ,中文稱“愚蠢窗口癥候群”,具體含義是,因為普遍終端應用程序每產生一次擊鍵操作就會發送一個包,而典型情況下一個包會擁有一個字節的數據載荷以及40個字節長的包頭,于是產生4000%的過載,很輕易地就能令網絡發生擁塞,。 Nagle化后來成了一種標準并且立即在因特網上得以實現。它現在已經成為缺省配置了,但在我們看來,有些場合下把這一選項關掉也是合乎需要的。
現在讓我們假設某個應用程序發出了一個請求,希望發送小塊數據。我們可以選擇立即發送數據或者等待產生更多的數據然后再一次發送兩種策略。如果我們馬上發送數據,那么交互性的以及客戶/服務器型的應用程序將極大地受益。例如,當我們正在發送一個較短的請求并且等候較大的響應時,相關過載與傳輸的數據總量相比就會比較低,而且,如果請求立即發出那么響應時間也會快一些。以上操作可以通過設置套接字的TCP_NODELAY選項來完成,這樣就禁用了 Nagle算法。
另外一種情況則需要我們等到數據量達到最大時才通過網絡一次發送全部數據,這種數據傳輸方式有益于大量數據的通信性能,典型的應用就是文件服務器。應用Nagle算法在這種情況下就會產生問題。但是,如果你正在發送大量數據,你可以設置TCP_CORK選項禁用Nagle化,其方式正好同 TCP_NODELAY相反(TCP_CORK 和 TCP_NODELAY 是互相排斥的)。下面就讓我們仔細分析下其工作原理。
假設應用程序使用sendfile()函數來轉移大量數據。應用協議通常要求發送某些信息來預先解釋數據,這些信息其實就是報頭內容。典型情況下報頭很小,而且套接字上設置了TCP_NODELAY。有報頭的包將被立即傳輸,在某些情況下(取決于內部的包計數器),因為這個包成功地被對方收到后需要請求對方確認。這樣,大量數據的傳輸就會被推遲而且產生了不必要的網絡流量交換。
但是,如果我們在套接字上設置了TCP_CORK(可以比喻為在管道上插入“塞子”)選項,具有報頭的包就會填補大量的數據,所有的數據都根據大小自動地通過包傳輸出去。當數據傳輸完成時,最好取消TCP_CORK 選項設置給連接“拔去塞子”以便任一部分的幀都能發送出去。這同“塞住”網絡連接同等重要。
總而言之,如果你肯定能一起發送多個數據集合(例如HTTP響應的頭和正文),那么我們建議你設置TCP_CORK選項,這樣在這些數據之間不存在延遲。能極大地有益于WWW、FTP以及文件服務器的性能,同時也簡化了你的工作。
轉自:
http://blog.chinaunix.net/u2/76292/showart.php?id=2105375