---------------------------------------------------------------------------------------------------------------------
狀況一: 單個client完整傳完
狀況二: client斷或server斷後續傳
狀況三: 多個client同ip同時傳,而某個client斷續傳
狀況四: 檔案已存在
狀況五: client網路斷掉timeout後離開再連Server續傳
狀況六: client網路斷掉後timeout之前連回去可續傳
---------------------------------------------------------------------------------------------------------------------
續傳程式大致上就幾個重點:
第一點是fseek的使用( http://linux.die.net/man/3/fseek )
fseek內的第一個參數fp2是檔案指標,第二個參數0代表指標要移動的offset值,第三個參數SEEK_END代表一種Action將指標移至最尾端。
check=fseek( fp2, 0, SEEK_END); //將檔案指標指到檔案最後.offset=0
total= ftell(fp2); //回傳指標所移動的值,代表從檔案指標從開始到目前位置共多長
第二點fseek前的檔案指標開啟:
我這裡先使用找檔案的指令放在程式碼裡面,讓接收端掃描要求的檔案如果存在就把檔案大小當offset傳給server告訴他client已有完整檔案而server退出process,client也會離開執行,否則就當作offset傳。
如果續傳的情況下,打開檔案指標沒有用 ” a+”反而直接以fseek移動檔案指標來寫檔案會出錯,因為原本fopen打開的型態是以可讀寫方式從頭開始,因此要改成從檔案尾開始讀取寫入,資料才不會亂碼。
if ( (fp = fopen(Filename, "a+")) == NULL){
perror_check("fopen continue error!");
}
第三點是signal的處理:
用來判斷fork後的child process是否還存在(判斷是否僵屍process),如果完整的結束並且離開會child process會發signal給系統,就會到signal handle function裡做處理,waitpid裡的 ”-1”代表等待所有產生的child process結束,” WNOHANG” 代表沒有child process存在時立即回到這行。
static void handle(int signum){
printf("clear! memory\n");
waitpid(-1,NULL,WNOHANG);
}
int main(int argc,char* arv[]){
signal(SIGCHLD,handle); //當fork後的child process完成後發出signal並前往handle處理
......}
最後要記得檔案內產生的副函式要加static防止其他檔案用到這個程式產生的副函式而產生錯誤,以及任何socket連線之後結束程式要close
=======================================================================
狀況一: 單個client完整傳完
左邊terminal是client端,右邊terminal是server端
client端連上server後,收到server端傳過來的檔名和大小,而client端先找自己有沒有該檔案
狀況一是client端沒有該檔案,因此回傳offset=0給server端,讓server從頭開始傳檔案。
client端連上server後,收到server端傳過來的檔名和大小,而client端先找自己有沒有該檔案
狀況一是client端沒有該檔案,因此回傳offset=0給server端,讓server從頭開始傳檔案。
完整正確傳完之後,server端要確定以fork出來在用傳送檔案的child process有沒有正確結束,不然會一直佔著記憶體空間。
驗證正確傳完的檔案有無損壞,解壓縮完就知道正確性。
========================================================================
狀況二: client斷或server斷後續傳
這是client端連回server端的開始畫面(在select timeout之後的重連),client端會先檢查本地有沒有該檔案,再來讀取檔案大小(offset)傳給server端並移動server端檔案指標到該offset的位置進行續傳。
從圖可以看到檔案續傳成功。
=======================================================================
狀況三: 多個client同ip同時傳,而某個client斷續傳
此圖左邊terminal為server端,右邊2個terminal位於同主機內不同資料夾下的client檔對server端進行連線,2個client端都沒有該檔案的情況下進行傳送檔案。
此圖顯示右邊client端連線中斷,但中間client端仍可以保持與server端的檔案傳送。
右邊client端連回server端的畫面(在select timeout之後的重連)即將從1.2G處開始續傳檔案,中間client不受右邊client端重連的影響,持續在傳送檔案。
顯示兩個client端的檔案都接收成功。
狀況四: 檔案已存在
特別做這個狀況的探討是因為檔案就算存在,也要確確實實檢查client端的檔案是否完整,檔案過大或少都代表與server端的檔案內容不符,因此即便傳完也得試著檢查檔案。
=======================================================================
狀況五: client網路斷掉timeout後離開再連Server續傳


=======================================================================
狀況六: client網路斷掉timeout後之前連回網路可續傳
如最後所示,連回去後的續傳檔案正確接收
========================================================================
最後,可能會對圖片內傳送檔案的數值有個疑問
" 明明buffer size設整數為什麼傳送或接收端的值不符合size大小值? "
那是因為傳送檔案的時候,不管有沒有跨網段,封包在傳送時不太可能會實際按照你設定的buffer size來做傳輸,反倒是依據網路情況來做分割封包或調整size大小值,因此值就有時大有時小,反之傳送程式buffer size設得太小的話,大概不會被改size值但電腦會對這個傳送程式的process吃非常大的CPU,所以設定size的大小要看當時的檔案來做選擇,這邊我是設50K來做測試。
沒有留言:
張貼留言