Bug(1)
程序要求:内网之间客户端截屏(.bmp)并传送给服务端。
server:
#include <winsock2.h> // 为了使用Winsock API函数 #include <stdio.h> #include <windows.h> #include<fstream> using namespace std; // 告诉连接器与WS2_32库连接 #pragma comment(lib,"WS2_32.lib") DWORD rem=0,num=0; void stranl(char *_str) { char _rem[16]; char _num[32]; int i,j=0; for(i=0;_str[i]!='#';i++) { _num[i]=_str[i]; } _num[i]='\0'; i++; for(;_str[i]!='\0';i++) { _rem[j]=_str[i]; j++; } _rem[j]='\0'; num=atoi(_num); rem=atoi(_rem); } int main(int argc, char* argv[]) { // 初始化WS2_32.dll WSADATA wsaData; WORD sockVersion = MAKEWORD(2, 0); ::WSAStartup(sockVersion, &wsaData); // 创建套节字 SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(s == INVALID_SOCKET) { printf("Failed socket() \n"); ::WSACleanup(); return 0; } // 填充sockaddr_in结构 sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(8888); sin.sin_addr.S_un.S_addr = INADDR_ANY; // 绑定这个套节字到一个本地地址 if(::bind(s, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) { printf("Failed bind() \n"); ::WSACleanup(); return 0; } // 进入监听模式 if(::listen(s, 2) == SOCKET_ERROR) { printf("Failed listen()"); ::WSACleanup(); return 0; } // 循环接受客户的连接请求 sockaddr_in remoteAddr; int nAddrLen = sizeof(remoteAddr); SOCKET client; char szCmd[32]; char szNumRem[32]; int i; char block[1024]; int BlkSize=0,allNum=0; char *allData=NULL; DWORD BmpSize=0; int nSize=0; while(TRUE) { // 接受一个新连接 client = ::accept(s, (SOCKADDR*)&remoteAddr, &nAddrLen); if(client == INVALID_SOCKET) { printf("Failed accept()"); continue; } printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr)); while(1) { printf("请输入命令:\n"); scanf("%s",szCmd); //分析命令 if(0!=strcmp(szCmd,"q")) //如果不是退出命令,则: { if(0==strcmp(szCmd,"scrshot")) // 如果是截屏命令,则: { // 向客户端发送命令,让其做好准备 ::send(client, szCmd, strlen(szCmd), 0); nSize = ::recv(client, szNumRem, 32, 0); if(nSize > 0) { szNumRem[nSize]='\0'; //解析字符串 printf("字符串:%s,大小:%d\n",szNumRem,nSize); stranl(szNumRem); printf("次数:%d,余数:%d\n",num,rem); BmpSize=num*1024+rem; allData = new char[BmpSize]; } printf("输入开始命令:"); scanf("%s",szCmd); ::send(client, szCmd, strlen(szCmd), 0); for(i=0;i<num;i++) { BlkSize = ::recv(client, block, 1024, 0); //if(BlkSize==1024) if(1) { memcpy(allData+1024*i,block,1024); } else { printf("我擦!\n"); system("pause"); } } BlkSize = ::recv(client, block, 1024, 0); if(BlkSize==rem) { memcpy(allData+1024*i,block,rem); } ofstream of("ClicentScreenShot.bmp",ios_base::binary); of.write(allData,BmpSize); printf("已完全接收图片!\n"); } } else break; } // 关闭同客户端的连接 ::closesocket(client); } // 关闭监听套节字 ::closesocket(s); // 释放WS2_32库 ::WSACleanup(); return 0; }
client:
#include <winsock2.h> // 为了使用Winsock API函数 #include <stdio.h> #include <windows.h> #include<fstream> using namespace std; // 告诉连接器与WS2_32库连接 #pragma comment(lib,"WS2_32.lib") char *allData=NULL; DWORD BmpSize=0; int main(int argc, char* argv[]) { // 初始化WS2_32.dll WSADATA wsaData; WORD sockVersion = MAKEWORD(2, 0); ::WSAStartup(sockVersion, &wsaData); // 创建套节字 SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(s == INVALID_SOCKET) { printf("Failed socket() \n"); ::WSACleanup(); return 0; } // 也可以在这里调用bind函数绑定一个本地地址 // 否则系统将会自动安排 // 填写远程地址信息 sockaddr_in servAddr; servAddr.sin_family = AF_INET; servAddr.sin_port = htons(8888); // 注意,这里要填写服务器程序(10ServerDemo程序)所在机器的IP地址 // 如果你的计算机没有联网,直接使用127.0.0.1即可 servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); if(::connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1) { printf("Failed connect() \n"); ::WSACleanup(); return 0; } // 接收命令 char szCmdBuff[32]; char str[32]; char tmp[16]; int i,j; char block[1024]; int nRecv = ::recv(s, szCmdBuff, 32, 0); if(nRecv > 0) { szCmdBuff[nRecv] = '\0'; printf("接收到命令:%s\n", szCmdBuff); } //命令处理 if(0==strcmp(szCmdBuff,"scrshot")) { //截屏,并计算图像大小 _ScreenSnap(); //每次发送1024字节,计算发送次数及剩余字节数 //格式: 次数#余数 DWORD rem=BmpSize%1024; DWORD num=BmpSize/1024; itoa(num,str,10); strcat(str,"#"); itoa(rem,tmp,10); strcat(str,tmp); printf("字符串:%s\n",str); ::send(s, str, strlen(str), 0); ::recv(s, szCmdBuff, 32, 0); if(0==strcmp(szCmdBuff,"start")) { for(i=0;i<num;i++) { for(j=0;j<1024;j++) block[j]=allData[i*1024+j]; ::send(s,block,1024,0); } for(j=0;j<rem;j++) block[j]=allData[num*1024+j]; ::send(s,block,num,0); } } // 关闭套节字 ::closesocket(s); // 释放WS2_32库 ::WSACleanup(); return 0; }
结果: