源碼:https://github.com/Lee-johnH/my_study.git
先上截圖:
首先我有個Faded.mp3的文件在目錄/mnt下,現在我要把它通過服務器傳給客戶端,傳到客戶端所在的文件目錄下,並命名為new_Faded.mp3.
先執行服務器,並輸入端口號,然后讓客戶端通過端口號向服務器發送連接請求,連接成功,服務器詢問應將哪個文件傳給客戶端,輸入原文件名,再輸入新文件名,文件傳輸過去,傳輸完畢則提示傳輸成功。客戶端用ls查看文件是否傳輸過來,目錄下多了個new_Fade.mp3,並確認可以使用該文件,傳輸成功!
實現思路:
服務器端:socket-->bind-->listen-->accept
客戶端: socket-->connect
服務器建立套接字為網絡通訊做基本准備,bind將本地的端口同socket返回的文件描述符捆綁在一起,listen函數將bind的文件描述符變為監聽套接字,然后調用accept函數進入阻塞狀態,直到客戶端程序發出連接請求,便建立全雙工通信。
建立連接之后,先在服務器輸入要傳輸的文件名,並保存在file_name[]數組當中,然后再輸入新的文件名存入file_name_save[]中,將新的文件名通過send()函數發送給客戶端,客戶端通過recv()函數接收,並以此名打開文件進行寫操作。
在傳送文件時我選擇使用一個零拷貝函數sendfile(),好處是在傳輸文件時無需進入用戶態,而是在內核態和磁盤直接就將文件傳輸過去,一來減少內核分配buffer的時間及空間,二來電腦無需從內核態切換到用戶態,再從用戶態切換到內核態,從而大大減少時間。保證在傳輸大文件時速度也很快,雲盤的秒傳技術用到了這個函數。
最后,文件傳輸完畢服務器提示傳輸成功,客戶端提示接收成功,並檢驗傳輸過來的文件是否可用。