日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ 使用socket实现C/S端文件的下载传输

發(fā)布時(shí)間:2023/12/2 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ 使用socket实现C/S端文件的下载传输 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

首先是服務(wù)器端,大致說下流程:服務(wù)器創(chuàng)建線程去處理應(yīng)答accept(),當(dāng)接受到客戶端連接請(qǐng)求時(shí),首先獲取要發(fā)送的指定的文件數(shù)據(jù)總大小給客戶端,接著就是循環(huán)讀取要發(fā)送的文件數(shù)據(jù)流向客戶端發(fā)送文件數(shù)據(jù),每次都判斷循環(huán)讀取到的數(shù)據(jù)實(shí)際大小,當(dāng)實(shí)際讀取到的數(shù)據(jù)總大小為0時(shí),表示文件發(fā)送結(jié)束。下面是服務(wù)器server端實(shí)現(xiàn):

聲明部分:

public:afx_msg void OnBnClickedButton1(); public:BOOL InitSocket(); //初始化并創(chuàng)建套接字static DWORD WINAPI ThreadProc(LPVOID lpParameter); //創(chuàng)建線程去執(zhí)行服務(wù)器accept()

實(shí)現(xiàn)部分:

void CSendFileServerDlg::OnBnClickedButton1() {// TODO: 在此添加控件通知處理程序代碼if (InitSocket()){GetDlgItem(IDC_EDIT1)->SetWindowText(_T("服務(wù)器開啟監(jiān)聽。。。 \r\n"));//創(chuàng)建線程HANDLE hThread = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);//關(guān)閉該接收線程句柄,釋放引用計(jì)數(shù) CloseHandle(hThread);} }BOOL CSendFileServerDlg::InitSocket() {//加載套接字庫 WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return FALSE;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {WSACleanup( );return FALSE;}//創(chuàng)建套接字//SOCKET m_socket=socket(AF_INET,SOCK_STREAM,0);m_socket=socket(AF_INET,SOCK_STREAM,0);if (m_socket == INVALID_SOCKET){AfxMessageBox(_T("套接字創(chuàng)建失敗!"));return FALSE;}SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(8099);err = bind(m_socket,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //綁定本地端口if (err==SOCKET_ERROR){closesocket(m_socket);AfxMessageBox(_T("綁定失敗!"));return FALSE;}listen(m_socket,5);//開啟監(jiān)聽return TRUE;}DWORD WINAPI CSendFileServerDlg::ThreadProc(LPVOID lpParameter) {SOCKADDR_IN addrClient;int len = sizeof(SOCKADDR);while (true){SOCKET sockConn=accept(m_socket,(SOCKADDR*)&addrClient,&len);CString filename = _T("E:\\test.zip");HANDLE hFile;unsigned long long file_size = 0;char Buffer[1024];DWORD dwNumberOfBytesRead;hFile = CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);file_size = GetFileSize(hFile,NULL);send(sockConn,(char*)&file_size,sizeof(unsigned long long)+1,NULL);do {::ReadFile(hFile,Buffer,sizeof(Buffer),&dwNumberOfBytesRead,NULL);::send(sockConn,Buffer,dwNumberOfBytesRead,0);} while (dwNumberOfBytesRead);CloseHandle(hFile);}return 0; }

如代碼所述? 每次發(fā)送單位是unsigned char[1024]大小(程序是char 應(yīng)該為unsigned char[1024])所以就不存在網(wǎng)絡(luò)字節(jié)序問題也不用考慮大端小端什么的。

服務(wù)器端暫時(shí)不支持多客戶端并發(fā)訪問,后續(xù)可能會(huì)加上。。。

-------------------------------------------

下面是客戶端,同樣也大致說下客戶端流程,客戶端增加手動(dòng)填寫Ip地址和端口號(hào)功能(端口號(hào)暫為8099)。以及下載傳輸文件數(shù)據(jù)進(jìn)度條的顯示,和下面簡(jiǎn)單的一些狀態(tài)顯示。客觀端由填寫的IP地址進(jìn)行連接服務(wù)器操作,如果客戶端連接服務(wù)器成功的話直接就會(huì)獲取服務(wù)器端發(fā)送的要發(fā)送的文件數(shù)據(jù)的總大小,如果獲取文件總大小>0 則會(huì)循環(huán)往指定的路徑寫數(shù)據(jù)啦。此處循環(huán)寫文件結(jié)束標(biāo)志,我是用每次實(shí)際寫的累加如果累計(jì)值等于從服務(wù)器端獲取的文件總大小的話表示下載文件數(shù)據(jù)成功,結(jié)束循環(huán)。大致是這樣一個(gè)過程。代碼實(shí)現(xiàn):

客戶端聲明部分:

public: ????afx_msg void?OnBnClickedButton1(); ????BOOL?InitSocket(); ????void?ConnectServer(); ????void?ConnectRecvFileData(DWORD?ip,int?port); private: ????CProgressCtrl *m_progress; //進(jìn)度條

?進(jìn)度條在OnInitDialog()里初始化:

BOOL CRecvFileClientDlg::OnInitDialog() {CDialog::OnInitDialog();// 將“關(guān)于...”菜單項(xiàng)添加到系統(tǒng)菜單中。// IDM_ABOUTBOX 必須在系統(tǒng)命令范圍內(nèi)。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 設(shè)置此對(duì)話框的圖標(biāo)。當(dāng)應(yīng)用程序主窗口不是對(duì)話框時(shí),框架將自動(dòng)// 執(zhí)行此操作SetIcon(m_hIcon, TRUE); // 設(shè)置大圖標(biāo)SetIcon(m_hIcon, FALSE); // 設(shè)置小圖標(biāo)// TODO: 在此添加額外的初始化代碼 m_progress = (CProgressCtrl*)GetDlgItem(IDC_PROGRESS1); m_progress->SetPos(0); return TRUE; // 除非將焦點(diǎn)設(shè)置到控件,否則返回 TRUE }

客戶端具體實(shí)現(xiàn)部分:

void CRecvFileClientDlg::OnBnClickedButton1() {// TODO: 在此添加控件通知處理程序代碼 ConnectServer();}BOOL CRecvFileClientDlg::InitSocket() {//加載套接字庫 WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return FALSE;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {WSACleanup( );return FALSE;}return TRUE;}void CRecvFileClientDlg::ConnectRecvFileData(DWORD ip,int port) {unsigned long long file_size=0;SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=htonl(ip);addrSrv.sin_port=ntohs(port);addrSrv.sin_family = AF_INET;//connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//recv(sockClient,(char*)&file_size,sizeof(unsigned long long)+1,NULL);if (!connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))){GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T(""));GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T("連接服務(wù)器成功!\r\n"));recv(sockClient,(char*)&file_size,sizeof(unsigned long long)+1,NULL);unsigned short maxvalue = file_size; //此處不太穩(wěn)妥 當(dāng)數(shù)據(jù)很大時(shí)可能會(huì)出現(xiàn)異常m_progress->SetRange(0,maxvalue); if (file_size>0){ GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T(""));GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T("文件下載到本地 d:\\test.zip \r\n"));DWORD dwNumberOfBytesRecv=0;DWORD dwCountOfBytesRecv=0;char Buffer[1024];CString filename = _T("d:\\test.zip");HANDLE hFile;hFile = CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);do {m_progress->SetPos(dwCountOfBytesRecv);//更新進(jìn)度條 dwNumberOfBytesRecv = ::recv(sockClient,Buffer,sizeof(Buffer),0);::WriteFile(hFile,Buffer,dwNumberOfBytesRecv,&dwNumberOfBytesRecv,NULL);dwCountOfBytesRecv += dwNumberOfBytesRecv; } while (file_size - dwCountOfBytesRecv);CloseHandle(hFile);GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T(""));GetDlgItem(IDC_SHOWINFO)->SetWindowText(_T("文件接收完畢!\r\n"));AfxMessageBox(_T("文件接收完畢!"));//醒目可以注釋}else{AfxMessageBox(_T("獲取文件總大小失敗!"));}}else{AfxMessageBox(_T("連接服務(wù)器失敗、請(qǐng)確認(rèn)IP地址或端口號(hào)!"));}closesocket(sockClient);//關(guān)閉套接字 }void CRecvFileClientDlg::ConnectServer() {if (InitSocket()){DWORD strIp =NULL;CString strPort = _T("");((CIPAddressCtrl*)GetDlgItem(IDC_IP))->GetAddress(strIp);GetDlgItem(IDC_PORT)->GetWindowText(strPort);if (strIp==NULL||strPort==""){AfxMessageBox(_T("Ip地址或Port端口號(hào)不能為空!"));}else{int port = atoi(strPort.GetBuffer(1));ConnectRecvFileData(strIp,port);}}} 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的c++ 使用socket实现C/S端文件的下载传输的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。