接上文,此代码是服务器段接受程序:
#include "stdafx.h" #include <winsock2.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <process.h> #pragma comment(lib,"ws2_32.lib") #define DEFAULT_PORT 5019 #define MAXCONNECTION 5 //暂时还不清楚多线程怎么个处理法,先用5个试试 #define MAXRECEIVELENGTH 1032 //1024+4+4 #define MAXSENDLENTH 100 //服务端反馈 数据包大小 void accept_conn(void *dummy); //疑问,是不是有一个连接到来,就需要实例化一个Socket 呢? 这是个问题没解决 SOCKET sock,new_socket; int main(int argc, char **argv){ int addr_len; struct sockaddr_in local, client_addr; WSADATA wsaData; //初始化套接字库 if (WSAStartup(0x202, &wsaData) == SOCKET_ERROR){ WSACleanup(); return -1; } //地址族初始化 local.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; local.sin_port = htons(DEFAULT_PORT); //TCp socket sock = socket(AF_INET,SOCK_STREAM, 0); if (sock == INVALID_SOCKET){ WSACleanup(); return -1; } //绑定侦听端口 if (bind(sock, (struct sockaddr *)&local, sizeof(local)) == SOCKET_ERROR){ WSACleanup(); return -1; } //侦听5个连接 这个侦听应该是系统的多线程在处理了 if (listen(sock, MAXCONNECTION) == SOCKET_ERROR){ WSACleanup(); return -1; } int connecting=1; while(true) { addr_len = sizeof(client_addr); new_socket=accept(sock, (struct sockaddr*)&client_addr, &addr_len); if (new_socket == INVALID_SOCKET){ WSACleanup(); return -1; } //多线程启动 线程函数是accept_conn //接受到一个就启动一个线程来处理 _beginthread(accept_conn, 0,NULL); Sleep(10);//避免CPU 100% } _endthread(); closesocket(sock); WSACleanup(); } void accept_conn(void *dummy) { char receiveBuff[MAXRECEIVELENGTH]={0}; char sendBuffer[MAXSENDLENTH]={0}; int msg_len=0;//接受数据长度 int msg_send_len=0; // 发送反馈数据长度 int addr_len; bool again=true; int realLength = 0; int crc32 = 0; struct sockaddr_in local, client_addr; SOCKET thread_socket=new_socket; //文件流 fstream walletFile; walletFile.open("d:\\test.txt",ios::binary|ios::out|ios::app); if(!walletFile.good()) { walletFile.close(); WSACleanup(); } while(again){ memset(sendBuffer,0,MAXSENDLENTH); memset(receiveBuff,0,MAXRECEIVELENGTH); msg_len = recv(thread_socket, receiveBuff, MAXRECEIVELENGTH, 0); //从client端发来的都是1032byte,不管那边封装实际有效数据(默认1024)够不够,都会封整个的包,整个包1032byte if(msg_len==MAXRECEIVELENGTH&&msg_len>0) { //取出实际有效数据长度 char lenbuff[4]={0}; memset(lenbuff,0,4); for(int ti =0;ti<4;ti++) { lenbuff[ti]=receiveBuff[1024+ti]; } memcpy(&realLength,lenbuff,4); //取出CRC32值 char crc32buff[4]={0}; memset(crc32buff,0,4); for(int tj =0;tj<4;tj++) { crc32buff[tj]=receiveBuff[1028+tj]; } memcpy(&crc32,crc32buff,4); //做crc32校验 int crc32value= Crc32(receiveBuff,realLength); //正确的话取出数据追加到文件 if(crc32value==crc32) { walletFile.write(receiveBuff,realLength); sendBuffer[0]='s'; sendBuffer[1]='e'; sendBuffer[2]='n'; sendBuffer[3]='d'; sendBuffer[4]='n'; sendBuffer[5]='e'; sendBuffer[6]='x'; sendBuffer[7]='t'; int senDataLenth=8;//蹩脚 int sendCrc32 = Crc32(sendBuffer,8); //这个是固定长度;其实就是"sendnext"的crc32值 memcpy(&sendBuffer[MAXSENDLENTH-4] ,&sendCrc32,4);//crc32 校验值 其实我觉得这个没必要。 memcpy(&sendBuffer[MAXSENDLENTH-8] ,&senDataLenth,4); msg_send_len = send(thread_socket, sendBuffer, MAXSENDLENTH, 0); } } else if(msg_len ==SOCKET_ERROR) //发完了 出错了 { walletFile.close(); WSACleanup(); } else{ //不得于 肯定传输中丢失了数据 int reTimes = 0; do{ sendBuffer[0]='r'; sendBuffer[1]='e'; sendBuffer[2]='s'; sendBuffer[3]='e'; sendBuffer[4]='n'; sendBuffer[5]='d'; int sendDataLenth = 6; //蹩脚 int sendCrc32 = Crc32(sendBuffer,6); //这个是固定长度;resend的crc32值 memcpy(&sendBuffer[MAXSENDLENTH-4] ,&sendCrc32,4);//crc32 校验值 其实我觉得这个没必要。 memcpy(&sendBuffer[MAXSENDLENTH-8] ,&sendDataLenth,4); msg_send_len = send(thread_socket, sendBuffer, MAXSENDLENTH, 0); reTimes++; }while(0==msg_send_len&&reTimes<100);//确保重发通知到位。100次 if(reTimes>=100) //100次还没发出去就说明 网络有问题;关闭连接; { walletFile.close(); closesocket(thread_socket); WSACleanup(); return; } continue; } if (msg_len == SOCKET_ERROR){ WSACleanup(); //return -1; } if (msg_len == 0){ closesocket(thread_socket); //return -1; } msg_len = send(thread_socket, sendBuffer, 100, 0); if (msg_len == 0){ closesocket(thread_socket); //return -1; } } closesocket(thread_socket); _endthread(); } unsigned int Crc32(char* InStr,unsigned int len){ //生成Crc32的查询表 unsigned int Crc32Table[256]; int i,j; unsigned int Crc; for (i = 0; i < 256; i++) { Crc = i; for (j = 0; j < 8; j++) { if (Crc & 1) Crc = (Crc >> 1) ^ 0xEDB88320; else Crc >>= 1; } Crc32Table[i] = Crc; } //开始计算CRC32校验值 Crc=0xffffffff; for(int i=0; i<len; i++){ Crc = (Crc >> 8)^ Crc32Table[(Crc & 0xFF) ^ InStr[i]]; } Crc ^= 0xFFFFFFFF; return Crc; }