socket實現大型檔案傳輸

2021-08-26 13:10:23 字數 3077 閱讀 9864

最近需要做網路傳輸的專案,需要實現較大檔案的傳輸。在網上收集了不少資料,但是各有各的做法,尤其是關於檔案自動接收這一塊不太清楚。 經過圖書館查閱後還是找到了一種解決辦法,雖然做的不太專業,但是思路比較精簡、清晰,也希望能給大家尤其是剛學習socket套接字的人一些啟示。

對於套接字socket我其實也不太懂,並且一般資料都可以查詢到,所以不交易累贅了,直接說如何實現檔案的傳輸吧。

對於傳送檔案,有三步:傳送檔案長度,傳送檔名,傳送檔案內容。

關於傳送檔案內容,又可以根據檔案大小進行直接傳輸和分塊傳輸,如果是分塊傳輸還需要多執行緒,否則會容易使程式失去響應。 在這裡其實我也有乙個疑惑,就是通過cfiledialog類getfilename函式獲取檔名,一般沒有問題,但是當檔名很長(如大於60)時不能完整讀取,導致接收方無法判別檔案型別。 所以保險起見,我就從getfilepath中截取出了檔名。

void cchatdlg::onsend() cfiledialog dlg(true); dlg.m_ofn.lpstrtitle="選擇"; dlg.m_ofn.lpstrfilter="all files"; cstring path=""; cstring name=""; if(dlg.domodal()==idok) if(path=="") return ;//表示沒有選擇任何元素 //不直接讀取檔名,而是從路徑名中擷取 int pos=0,start=0; while(1) name=path.right(path.getlength()-start-1); file.open(path,cfile::moderead);//開啟檔案 dwlen=file.getlength();//獲取檔案長度 m_se.setrange32(0,dwlen); cstring te; te.format("%d",dwlen); if(flag==0)//傳送資料 send(m_accept, te.getbuffer(0), 10, 0);//傳送檔案的長度 if(flag==1) send(m_local, te.getbuffer(0), 10, 0); sleep(500);//延時 if(flag==0)//傳送資料 send(m_accept, name.getbuffer(0), name.getlength(), 0);//傳送檔案的名 if(flag==1) send(m_local, name.getbuffer(0), name.getlength(), 0); sleep(500);//延時 if(dwlen<=1024*1024)//如果小於1m就直接傳輸 date=new char[dwlen];//開闢neicun memset(date,0,dwlen);//初始化 file.read(date,dwlen);//讀取檔案 file.close(); int n=0; if(flag==0)//傳送資料 n=send(m_accept, date, dwlen, 0); if(flag==1) n=send(m_local, date, dwlen, 0); m_se.setpos(n); cstring ss; ss.format("%d %d",dwlen,n); ss+="傳送完成"; messagebox(ss); delete date; date=null; } else }

註解中的什麼的是錯誤的,是可以傳輸任意格式的檔案的。大家可以看到我提取檔名的過程繁瑣,原因我

上面一段已經說明了,也希望大家更好的解決方法。其中flag的值時表示是服務端還是客戶端,0-服務端,1-客戶端,集合在了乙個程式中。

注意::: 其中的sleep(500)的延時是因為為了讓接受方有足夠多的時間獲取檔案長度和檔名關鍵資訊,如果不延時,接收方會先接受到檔案內容後接收到檔案長度和檔名,順序是相反的,具體原因我也沒弄清楚,希望大家指教。

最後是關於乙個執行緒的函式,具體如下:

uint send(lpvoid pthreadparam)//執行緒函式 int total=0,len=0; while(total=1024*100) else sleep(1); total+=len;//累計已經傳送的資料 dlg->m_se.setpos(total); delete date; date=null; //**記憶體空間 } file.close(); cstring ss; ss.format("%d",total); ss+="傳送完成"; messagebox(dlg->m_hwnd,ss,"提示",mb_ok); dword exit=0; bool ret=getexitcodethread(dlg->p_thread->m_hthread,&exit);//獲取執行緒退出** if(exit==still_active) //如果程序仍在進行 return 0; }

執行緒的好處是不會讓程式失去響應,而且對於大型檔案傳輸來說這是必須的。

其次,關於檔案的接受,就是乙個註冊的onsocket中的fd_read,通過這個方式設定wsaasyncselect模型的。

int nret = wsaasyncselect(m_local, m_hwnd, wm_socket, fd_accept|fd_connect|fd_read|fd_write|fd_close); if (nret != 0) 關於onsocket 函式完整如下,處理fd_read|fd_connect|fd_accept等訊息

void cchatdlg::onsocket(wparam wparam,lparam lparam) case fd_read: //接收資料 temp=new char[1024*56];//開闢乙個記憶體 memset(temp,0,1024*56); x=recv(sock,temp,1024*56,0); f.write(temp,x); total+=x; m_get.setpos(total); delete temp; temp=null; if(total>=m_length)//表示接受完成 break; } } break; case fd_close: case fd_connect: //連線網路事件 break; } } }

其中接受就在fd_read訊息中,flag1-1接受檔案長度,flag1-2接受檔名,flag1-3接受檔案內容。

當然整個函式太長了,本來應該一些語句應該設定成一些函式的,那樣也更直觀。

這基本上是這個工程的全部了,還是比較簡潔的。在同一臺電腦上測試結果是:732577734位元組共耗時114秒,平均6.12m/s,也不是體太慢。

整個專案還是有不少弊端的,有疑惑的可以相互交流討論。

socket檔案傳輸

伺服器 本檔案是伺服器的 include for sockaddr in include for socket include for socket include for printf include for exit include for bzero include for time t an...

socket檔案傳輸

最近入職培訓中需要寫乙個linux下的c s網路檔案傳輸工具,在實現的過程中,遇到了一些坑,在這裡 做個總結 由於udp伺服器不需要accept 因此也沒有link id 連線的客戶端id 在伺服器檔案接收或下發檔案時需要知道當下與之通訊的客戶端的識別符號,由於udp是無連線的,並且sockfd s...

Socket檔案傳輸

服務端 輸入檔案完整路徑傳送給客戶端 import struct import json import os tcp server socket ip port 127.0.0.1 8080 buffsize 1024 埠的重複利用 tcp server.bind ip port tcp serve...