76)客户端往服务器发文件
https://www.cnblogs.com/my_life/articles/5363527.html
基础:
其实就是在TCP的那个解决方案里面,加一个SendFile的工程,在工程里面建一个SendFile.cpp的文件,里面放CLient的代码
同时进行修改代码,SendFile代码:
1 #include<iostream> 2 #include<Winsock2.h> 3 4 #include<fstream> 5 6 using namespace std; 7 8 #pragma comment(lib, "ws2_32.lib") 9 10 struct FileHeader 11 { 12 char fileName[MAX_PATH]; 13 int fileSize; 14 }; 15 int main() 16 { 17 18 //第一步 19 WORD wVersionRequested; 20 WSADATA wsaData; 21 int err; 22 23 24 wVersionRequested = MAKEWORD(2, 2); 25 26 err = WSAStartup(wVersionRequested, &wsaData); 27 if (err != 0) { 28 printf("WSAStartup failed with error: %d\n", err); 29 return 1; 30 } 31 32 33 34 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { 35 36 printf("Could not find a usable version of Winsock.dll\n"); 37 WSACleanup(); 38 return 1; 39 } 40 else 41 printf("The Winsock 2.2 dll was found okay\n"); 42 43 //第二步: 44 45 SOCKET sock=socket(AF_INET ,SOCK_STREAM,IPPROTO_TCP ); 46 if(sock==INVALID_SOCKET) 47 { 48 WSACleanup(); 49 return 1; 50 } 51 52 //第三步 53 cout<"请输入服务器IP:"<<endl; 54 char szip[100]={0}; 55 cin>>szip; 56 57 sockaddr_in clientService; 58 InetPton(AF_INET,szip,(void*)&addr.sin_addr.S_un.S_addr);//这是干啥的,我都不知道 59 60 clientService.sin_family = AF_INET; 61 //clientService.sin_addr.s_addr = inet_addr("192.168.3.153"); 62 clientService.sin_port = htons(1234); 63 64 connect(sock,(SOCKADDR *) & clientService, sizeof (clientService)); 65 66 67 //第七步 68 char filePath[MAX_PATH]={0}; 69 char *pfilePath=filePath; 70 //发东西了 71 //文件头-->包含文件名和文件大小(两种数据类型,所以发一个结构体就行了,所以在上面定义一个结构体FileHeader) 72 FileHeader fh; 73 cout<<"请输入要传输的文件:"<<endl; 74 cin>>filePath; 75 //我们要从带有文件名的路径里面获得文件名; 76 while(*pfilePath++!='\0'); 77 //现在pfilePath就指到最后一个字母那块了,现在开始往回走 78 while(*(--pfilePath)='\\');//只要读到\,就停下来 79 pfilePath++; 80 strcpy_s(fh.fileName,MAX_PATH,pfilePath);//获得文件名 81 //接下来获得文件大小,因为文件只有打开才能获得文件大小,所以 我们接下来就是打开文件,但是C里面没有获得文件大小的函数,C++里有,MFC里有 82 83 //C++这个里面有获取文件大小的函数#include<fstream> 84 fstream fs; 85 fs.open(filePath,fstream::in|fstream::binary);//以二进制流的形式读,无论是什么文件,这样都能读出来 86 //在C++没有直接获得文件大小的函数,但是他有获得文件指针所指的文件大小的函数,所以下面我要移动文件指针,文件指针最开始指向文件头,我要把文件指针移到文件尾,然后才是获得的整个文件的大小 87 88 fs.seekg(0,fs::end);//移动文件指针到尾部,不偏移 89 90 fh.fileSize=fs.telg();//获得文件指针位置的文件大小 91 fs.seekg(0,fs::beg);//移动文件指针到头部,不偏移(就是再移回去) 92 93 94 95 96 //发送 97 send(sock,(const char*)&fh,sizeof(fh),0); 98 99 100 //等待对方回复--> 101 char sResult[4]={0};//存来自服务器的答复内容 102 char content_buffer[1024]={0}; 103 recv(sock,sResult,sizeof(sResult),0); 104 105 if(0==strcmp(sResult,"是"))//如果肯定回复--》 106 { 107 108 while(1) 109 { 110 //读文件, 111 fs.read(content_buffer,sizeof(content_buffer)); 112 //发文件 113 //应该是读多少就发多少,而不应该是固定发多少,因为有可能,我读到的文件内容小于你设定的读的文件的大小 114 int RealResultNum=fs.gcount();//获得当前真正读的文件大小 115 if(RealResultNum==0) 116 { 117 break; 118 } 119 send(sock,content_buffer,RealResultNum); 120 } 121 122 123 } 124 125 //关闭文件 126 fs.close(); 127 128 //第八步 129 130 closesocket(sock); 131 WSACleanup(); 132 return 1; 133 134 135 136 137 138 139 system("pause"); 140 return 0; 141 }
修改服务器代码: