利用WinSocket发数据(二)

接上文,此代码是服务器段接受程序:

#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 

#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> 8)^ Crc32Table[(Crc & 0xFF) ^ InStr[i]];     
    }  
      
    Crc ^= 0xFFFFFFFF;  
    return Crc;     
} 


你可能感兴趣的:(win32,c++,技术)