接上文,此代码是服务器段接受程序:
#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;
}