写了一个接收模块,很简单,错误也很奇怪 指针问题
#include <stdio.h>#include "InterWin.h"#include <IniFiles.hpp>//---------------------------------------#pragma package(smart_init)static CRITICAL_SECTION Memcopy;//公共缓冲区临界区static TAG_INTERBUF InterBuf;// 公共缓冲区static bool IsRun;static CMsgServer *Serv;TInterWin::TInterWin(CMsgServer *msgServer){ Serv = msgServer; IsListen = false; IsRun = false;}TInterWin::~TInterWin(){ //删除临界区 DeleteCriticalSection(&Memcopy); if(sockSrv != NULL) delete sockSrv; //delete TagArgs->Args; if(Arg != NULL) delete Arg;}//socket初始化bool __fastcall TInterWin::Listen(){ //定义版本号 WORD wVersionRequested; WSADATA wsaData; int err; if(IsListen) return false; IsListen = true; wVersionRequested = MAKEWORD( 2, 2 ); TIniFile *ini; ini = new TIniFile(ChangeFileExt(Application->ExeName, ".ini" )); //读取工作模式 int Port =ini->ReadInteger("TCPIP", "Port", 0); //缺省为服务器模式 delete ini; err = WSAStartup( wVersionRequested,&wsaData); if( err != 0) { return false; } //版本是否正确 if( LOBYTE( wsaData.wVersion)!= 2|| HIBYTE(wsaData.wVersion)!= 2) { WSACleanup(); return false; } sockSrv = new SOCKET; //创建socket IPV4 TCP *sockSrv = socket(AF_INET,SOCK_STREAM,0); //服务端结构体 SOCKADDR_IN addrSrv; memset(&addrSrv,0,sizeof(SOCKADDR_IN)); addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//IP地址 htonl:将主机字符顺序转化成网络顺序 addrSrv.sin_family = AF_INET; //协议类型 IPV4 addrSrv.sin_port= htons(Port);//端口号 16位主机字符转化网络字符 ///梆定socket到端口 bind(*sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); err = listen(*sockSrv,128); //第二个参数表示最大连接数 当为AF_INET时最大是128 if(err!=0) { //getErrors err = WSAGetLastError(); } Arg = new TAG_THREADARG; Arg->Args = (void *)sockSrv; //Arg->handle = m_hWnd; //初始化临界区 InitializeCriticalSection(&Memcopy); //开始监听线程 _beginthreadex(NULL , 0 ,StartListenThread,(void *)Arg , 0 , 0); //数据传递线程 //_beginthreadex(NULL , 0 ,SendDataThread,NULL , 0 , 0); return true; }//==============================================================================// 端口监听线程 阻塞模式//==============================================================================unsigned __stdcall TInterWin::StartListenThread(void* pArguments ){ Sleep(5000); TAG_THREADARG *TagArgs = (TAG_THREADARG *)(pArguments); SOCKET *test = (SOCKET *)TagArgs->Args; //(TAG_THREADARG *)(pArguments) while(true) { SOCKADDR_IN addrClient; int len = sizeof(SOCKADDR); SOCKET sockConn = accept(*test,(SOCKADDR*)&addrClient,&len); //设置接收超时时间 超时自动断开连接 //int timeout = 40*1000; //int itemp = setsockopt(sockConn,SOL_SOCKET,SO_RCVTIMEO, (const char *)&timeout,sizeof(int)); //连接信息加入映射表· //ClientList.insert(map<unsigned int, SOCKADDR_IN>::value_type(sockConn,addrClient)); TAG_THREADARG *info = new TAG_THREADARG; SOCKET *sock = new SOCKET; *sock = sockConn; info->Args = (void *)sock; //info->handle = TagArgs->handle; _beginthreadex(NULL , 0 ,disposeMessageThread,(void *)info , 0 , 0); } return 0;}//==============================================================================// 消息接收线程//==============================================================================unsigned __stdcall TInterWin::disposeMessageThread(void* pArguments){ TAG_THREADARG *info = (TAG_THREADARG *)pArguments; SOCKET *sock = (SOCKET *)info->Args; BYTE *ListBuf = new BYTE[ECGDATABUF]; //每包81个字幕 每400ms一次。定 7*81个缓冲区 约2.8秒的数据 ZeroMemory(ListBuf,ECGDATABUF); unsigned int *Position = new unsigned int; //标志缓冲区的结束位置 *Position = 0; //delete info->Args; //info->Args = NULL; char revBuf[ECGDATABUF]; //这是接收缓冲区 while(true) { memset(revBuf,0,ECGDATABUF); int recleng = recv(*sock,revBuf,ECGDATABUF,0); if(recleng <= 0 || IsRun == true) {//连接断开 //将连接在连接列表中去除 shutdown(*sock ,2);//关闭套接字 delete sock; delete info; delete[] ListBuf; delete Position; break; } //printf("%x",revBuf[0]); //没有超过缓冲区才处理 if((*Position + recleng) < ECGDATABUF) { memcpy(ListBuf + *Position,revBuf,recleng); //复制到缓冲区 *Position += recleng; } else {//为了接收最新的数据,将前面接收到的数据进行丢弃 //memmove(&ListBuf[0],&ListBuf[recleng], 567-recleng); //memcpy(ListBuf + *Position,revBuf,recleng); //ZeroMemory(&ListBuf[0],ECGDATABUF); //*Position = 0; } //if(*Position >= 1050)//凑够5秒数据一起发 //{ DisposeData(ListBuf,Position); //} } return 1;}//==============================================================================// 判断是否是完整数据包 //==============================================================================unsigned __stdcall TInterWin::DisposeData(BYTE *DataBuf, unsigned int *pos){ int bufstart = 0; //数据包在缓冲区的开始位置 int bufend = 0; //数据包在缓冲区的结束位置 bool isok = false; int dataleng = 0; int i; unsigned int Count = *pos; //注意 循环中不能移动数据包 否则i指的位置错误 低级错误 for(i = 0; i < Count; i++) { if(DataBuf[i] == 0x55 && DataBuf[i+1] == 0xAA) { if(bufstart == 0 && bufend == 0 && isok == false) {//这是第一次检测到同步字 bufstart = i; //记录同步字开始位置 isok = true; //表示前面已经检测到同步字了 } else if(isok == true) {//这是第二次检测到同步字表示前面已经有完整的数据表了 bufend = i; //结束位置 dataleng = bufend - bufstart; EnterCriticalSection(&Memcopy); Serv->packetParser(&DataBuf[bufstart],dataleng); //收到包直接发,不用公共缓冲区 LeaveCriticalSection(&Memcopy); //memmove(&DataBuf[0],&DataBuf[dataleng], ECGDATABUF - dataleng);//移动缓冲区 //*pos -= dataleng; //改变结束位置 //这个第二包的开始,因为上面已经检测到同步字了。 bufstart = bufend;// - dataleng); //bufend = 0; //isok = false; } } } //循环结束判断是否有数据包(只有一个数据包的情况) if(isok == true) //有同步字 { if(DataBuf[bufstart] == 0x55 && DataBuf[bufstart+1] == 0xAA) { //if((DataBuf[*pos-1]&0xFF) == (*pos-2)) //先不进行校检和检测 { EnterCriticalSection(&Memcopy); Serv->packetParser(&DataBuf[bufstart],84); LeaveCriticalSection(&Memcopy); isok = false; bufstart += 84; } } } memmove(&DataBuf[0],&DataBuf[bufstart], ECGDATABUF - bufstart);//移动缓冲区 *pos -= bufstart; //改变结束位置 if(*pos < 0) *pos = 0; return 0;}//数据发送线程unsigned __stdcall TInterWin::SendDataThread(void* pArguments){ /* while(true) { if(InterBuf.position < 83) { Sleep(30); continue; } EnterCriticalSection(&Memcopy); Serv->packetParser(InterBuf.Buff, InterBuf.position); LeaveCriticalSection(&Memcopy); Sleep(10); } */ return 0;}