Windows Socket程式設計之UDP實現大檔案的傳輸
阿新 • • 發佈:2019-01-09
前言:
本文實現以下功能:
在客戶端,使用者選擇本地的某個檔案,併發送到伺服器端。
在伺服器端,接收客戶端傳輸的資料流,並按IP 地址儲存在伺服器端(文
件名重複的,可以覆蓋)。
如果傳輸過程中伺服器端發現客戶端斷開,伺服器端應刪除檔案,並在螢幕
上提示,如“IP:1.2.3.4 發來abcd.txt 檔案過程中失去連線。”。如果客戶端發
現伺服器端不工作,客戶端應有提示“伺服器1.2.3.5:62345 失去連線”。
一、UDP傳輸流程圖
二、程式碼實現
1.1.FileHelper用來進行與檔案相關的操作
#include<stdio.h> #include<stdlib.h> #include <WINSOCK2.H> #include <STDIO.H> #pragma comment(lib,"ws2_32.lib") class FileHelper { private: FILE *f; char path_buffer[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; public: FILE * selectfile() { printf("請輸入要傳送的檔名\n"); scanf("%s",path_buffer); if (f=fopen(path_buffer,"rb")) { printf("檔案開啟成功\n"); return f; } else { printf("檔案不存在,請重新輸入\n"); return selectfile(); } } char * getFileName() { _splitpath(path_buffer, drive, dir, fname, ext); return strcat(fname, ext); } FILE * createFile(char *name) { remove(name); if (f = fopen(name, "ab")) { printf("檔案建立成功\n"); } else { printf("檔案建立失敗\n"); } return f; } bool createDir(char *dir) { char head[MAX_PATH] = "md "; return system(strcat(head, dir)); } };
2.Client端
#pragma comment(lib,"Ws2_32.lib") #include<WinSock2.h> #include<WS2tcpip.h> #include<stdio.h> #include<Windows.h> #include"FileHelper.h" int main() { WORD wVersionRequested; WSADATA wsaData; char sendData[BUFSIZ]="ÄãºÃ£¡\n"; char beginData[BUFSIZ]="Begin\n"; char overData[BUFSIZ]="Over\n"; char Filename[BUFSIZ]={}; FileHelper fh; int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { /* Tell the user that we could not find a usable */ /* Winsock DLL. */ printf("WSAStartup failed with error: %d\n", err); return 1; } if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ printf("Could not find a usable version of Winsock.dll\n"); WSACleanup(); return 1; } SOCKADDR_IN addrServ; addrServ.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); addrServ.sin_family=AF_INET; addrServ.sin_port=htons(4999); while (true) { SOCKET socketClient=socket(AF_INET,SOCK_DGRAM,0); FILE *f=fh.selectfile(); sendto(socketClient,beginData,BUFSIZ,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR)); strcpy(Filename,fh.getFileName()); sendto(socketClient,Filename,BUFSIZ,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR)); int count=0; int sum=0; while ((count=fread(sendData,1,BUFSIZ,f))>0) { Sleep(1); printf("%d\n",sum+=count); sendto(socketClient,sendData,BUFSIZ,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR)); } sendto(socketClient,overData,BUFSIZ,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR)); closesocket(socketClient); } WSACleanup(); return 0; }
3.Servet端
#pragma comment(lib,"Ws2_32.lib") #include<WinSock2.h> #include<WS2tcpip.h> #include<stdio.h> #include<Windows.h> #include "FileHelper.h" int main() { WORD wVersionRequested; WSADATA wsaData; FileHelper fh; int err; wVersionRequested=MAKEWORD(2,2); err=WSAStartup(wVersionRequested,&wsaData); if (err!=0) { printf("WSAStartup failed with error:%d\n",err); return -1; } if (LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2) { printf("Could not find a usable version of Winsock.dll\n"); WSACleanup(); return -1; } SOCKET socketServer=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); SOCKADDR_IN addrServ; addrServ.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//指定0.0.0.0地址,表示任意地址 addrServ.sin_family=AF_INET;//表示IPv4的套接字型別 addrServ.sin_port=htons(4999); bind(socketServer,(SOCKADDR*)&addrServ,sizeof(SOCKADDR)); SOCKADDR_IN addrClient; int length=sizeof(SOCKADDR); char recvBuf[BUFSIZ]={}; int rev=0; while (true) { DWORD TIME_OUT=10; char sendData[BUFSIZ]="你好!\n"; char beginData[BUFSIZ]="Begin\n"; char overData[BUFSIZ]="Over\n"; char Filename[BUFSIZ]={}; char ClientAddr[BUFSIZ]={}; char FromName[BUFSIZ]={}; FILE *f=NULL; if(err=setsockopt(socketServer,SOL_SOCKET,SO_SNDTIMEO,(char *)&TIME_OUT,sizeof(TIME_OUT))) { printf("失敗!\n"); }; printf("%d\n",err); recvfrom(socketServer,recvBuf,BUFSIZ,0,(SOCKADDR*)&addrClient,&length); if (strcmp(recvBuf,beginData)==0) { recvfrom(socketServer,recvBuf,BUFSIZ,0,(SOCKADDR*)&addrClient,&length); strcpy(ClientAddr,inet_ntoa(addrClient.sin_addr)); strcpy(FromName,recvBuf); fh.createDir(ClientAddr); strcpy(Filename,ClientAddr); strcat(Filename,"\\"); strcat(Filename,recvBuf); f=fh.createFile(Filename); } int sum=0; while((rev=recvfrom(socketServer,recvBuf,BUFSIZ,0,(SOCKADDR*)&addrClient,&length))>0) { if (strcmp(overData,recvBuf)==0) { printf("檔案%s傳輸成功!\n",FromName); fclose(f); break; } // printf(recvBuf); fwrite(recvBuf,1,rev,f); printf("%db\n",sum+=rev); } if (rev<0||strcmp(overData,recvBuf)!=0) { printf("IP:%s發來的%s傳輸過程中失去連線\n",addrClient,FromName); fclose(f); remove(Filename); } } closesocket(socketServer); WSACleanup(); return 0; }