- //***********************************************************************************
- //文件说明:TSocket.h
- //功能: 文件传输客户端实现头文件
- //使用说明:使用TCP的IOCP实现,可以传送大消息包、文件,同一客户端可以同时发送多个文件
- // 1、用TClients创建一个对象,pClients
- // 2、调用pClients->CreateClient(...)函数,参数1、2是要连接的服务端IP和端口,
- // 3服务端返回消息的事件回调处理函数,4是服务端断开连接的事件回调处理函数
- // 3、调用pClients->SendMsg(...)给对端发消息
- // 4、调用pClients->SendFile(...)给对端发文件
- // 5、调用pClients->Disconnet(...)主动断开连接
- // 6、销毁pClients对象
- //时间: 2010.5.1 23:13:56
- //作者: 废人
- //留待实现:
- // bool SendFileToAll(const char * filename);
- // bool SendFileToServers(SOCKETS sClients,const char * filename);
- // bool SendFileToOther(SOCKET ExceptSocket,char * pData,ULONG Length);
- // bool SendMsgToAll(char * pData,ULONG Length);
- // bool SendMsgToServers(SOCKETS sClients,char * pData,ULONG Length);
- // bool SendMsgToOther(SOCKET ExceptSocket,char * pData,ULONG Length);
- //***********************************************************************************
- #if !defined(AFX_TSOCKET_H__46FFF420_23C3_4356_A88D_AEBDA61EA186__INCLUDED_)
- #define AFX_TSOCKET_H__46FFF420_23C3_4356_A88D_AEBDA61EA186__INCLUDED_
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- #include <list>
- #include <afxtempl.h>
- #include <winsock2.h>
- #include <vector>
- #include <queue>
- #include <string>
- #include <algorithm>
- #include <map>
- #pragma comment(lib,"ws2_32.lib")
- using namespace std;
- #pragma warning(disable:4786)
- //服务端口
- #define SVRPORT 10012
- //缓冲区大小
- #define BUFFER_SIZE 4096
- //接收数据
- #define RECV_POSTED 0
- //发送数据
- #define SEND_POSTED 1
- class TClient;
- class TClients;
- struct TPack;
- //单句柄数据
- typedef struct _PER_HANDLE_DATA
- {
- TClient *client;
- }PER_HANDLE_DATA,*LPPER_HANDLE_DATA;
- //IO操作数据
- typedef struct _PER_IO_OPERATION_DATA
- {
- //重叠结构
- OVERLAPPED OverLapped;
- //数据缓冲区
- WSABUF RecvDataBuf;
- WSABUF SendDataBuf;
- char RecvBuf[BUFFER_SIZE];
- char SendBuf[BUFFER_SIZE];
- //操作类型表示
- bool OperType;
- }PER_IO_OPERATION_DATA,*PPER_IO_OPERATION_DATA;
- typedef map<SOCKET,TClient*> TSortClients; //排序的客户端
- typedef map<ULONG,TPack *> TPacks; //有些数据包需要重组才能合成大数据包回调ProcessRecvData函数,占时保存结构
- typedef vector<SOCKET> SOCKETS;
- //回调处理数据函数原型
- typedef void __stdcall ProcessRecvData(char * pData,ULONG DataLength);
- typedef void __stdcall ProcessPeerClose();
- typedef void __stdcall ProcessFileTransfer(char *filename,double speed);
- DWORD WINAPI ServerWorkerProc(LPVOID lParam); //工作线程
- DWORD WINAPI ListenProc(LPVOID lParam);
- ULONG ULSize=sizeof(ULONG);
- ULONG cSize=sizeof(char);
- class TData
- {
- public:
- char *data;
- ULONG totalLen;
- char *Cur;
- void AddType(char type);
- void AddInt(ULONG len);
- void AddData(char *buf,ULONG len);
- char GetType();
- ULONG GetInt();
- char* GetData(ULONG &retlen);
- };
- struct TPack
- {
- char *data;
- char *CurPack;
- ULONG totalLen;
- void clear()
- {
- CurPack=data;
- totalLen=0;
- }
- void AddData(char*d,ULONG len)
- {
- memcpy(CurPack,d,len);
- CurPack+=len;
- totalLen+=len;
- }
- };
- struct TDataMod //用于传输的模型,用malloc和free,大小不超过BUFFER_SIZE
- {
- char type; //0单独数据包,1连续消息数据包头,2文件数据包头,3连续包的消息体,4文件包的消息体,5是否需要销毁本指针
- ULONG Len;
- ULONG Channel;
- char data;
- //1、连续消息第一个包的 Len是长度,Channel是Send的传输号,以后Len就是Send的传输号
- //2、文件消息第一个包的 Len是长度,Channel是Send的传输号,以后Len就是Send的传输号
- //3、单独包是只有Len长度,Index是数据内容
- };
- struct TFileDataHead
- {
- char type;
- ULONG Channel;
- TCHAR szFileTitle[128]; //文件的标题名
- DWORD dwFileAttributes; //文件的属性
- FILETIME ftCreationTime; //文件的创建时间
- FILETIME ftLastAccessTime; //文件的最后访问时间
- FILETIME ftLastWriteTime; //文件的最后修改时间
- DWORD nFileSizeHigh; //文件大小的高位双字
- DWORD nFileSizeLow; //文件大小的低位双字
- DWORD dwReserved0; //保留,为0
- DWORD dwReserved1; //保留,为0
- TCHAR cAlternateFileName;
- TCHAR cFileName;
- };
- //消息包的类型:
- //1、单独数据包(TData),type==0,Len为长度,data开始存储的是数据 (MinDataLen)
- //2、连续消息数据包头,type==1,Len为消息体总长度,Channel是当前通道号,data信息数据(MinDataHeadLen)
- //3、连续消息中间数据包,type==3,Len为Channel号,data信息数据(MinDataLen)
- //4、文件头TFileDataHead,type==2
- //5、文件中间数据包,type==4,Len为Channel号,data信息数据(MinDataLen)
- ULONG MinDataLen=ULSize+cSize;
- ULONG MinDataHeadLen=MinDataLen+ULSize;
- ULONG MinFileHeadLen=sizeof(TFileDataHead);
- class TClient //用于中间实现的类,不能直接使用
- {
- public:
- TClient();
- ~TClient();
- void OnReceive(char *data,ULONG len);//data是一个全局指针
- private:
- void clear();
- ProcessPeerClose *m_pfPeerClose;
- //客户端消息回调函数
- ProcessRecvData *m_pfRecvData;
- //本端管理者指针
- TClients *m_ClientManager;
- //临时存放分块数据包进行组装
- TPacks m_Receivepacks;
- //本端的SOCKET号
- SOCKET m_Sock;
- //对端的IP
- char m_RemoteIP[16];
- //对端的端口
- ULONG m_RemotePort;
- //临时存放不足一帧的数据
- TPack m_tempDta;
- friend DWORD WINAPI ServerWorkerProc(LPVOID lParam);
- friend class TClients;
- };
- class TClients //外部接口类,可以用其公有方法接口
- {
- public:
- TClients(LPCTSTR strLogPath="TClientsLog.log");
- ~TClients();
- SOCKET CreateClient(const char *pSerIp,ULONG iSvrPort=SVRPORT,
- ProcessRecvData* OnProcessRecvData=NULL,ProcessPeerClose* OnProcessPeerClose=NULL);
- bool Disconnet(SOCKET sClient);
- bool DisconnetAll();
- bool SendMsg(SOCKET sClient,char * pData,ULONG Length);
- bool SendFile(SOCKET sClient,const char * filename,ProcessFileTransfer *OnFileTrans=NULL){return true;}
- bool GetRemoteAddress(SOCKET sClient,char * IP,ULONG &port);
- bool GetLocalIP(char *&IP);
- private:
- //完成句柄
- HANDLE CompletionPort;
- //客户信息临界保护量
- CRITICAL_SECTION cClientSection;
- //当前发送的通道号
- ULONG Channel;
- //客户信息列表
- TSortClients m_clients;
- //写日志文件
- char m_LogPath[MAX_PATH];
- void WriteLogString(const char *format,...);
- void InitNetWork();
- void UnInit();
- private:
- friend class TClient;
- friend DWORD WINAPI ServerWorkerProc(LPVOID lParam);
- };
- #endif // !defined(AFX_TSOCKET_H__46FFF420_23C3_4356_A88D_AEBDA61EA186__INCLUDED_)
- <pre name="code" class="cpp">//***********************************************************************************
- //文件说明:TSocket.cpp
- //功能: 文件传输客户端实现头文件
- //使用说明:使用TCP的IOCP实现,可以传送大消息包、文件,线程安全同一客户端可以同时发送消息、文件
- // 1、用TClients创建一个对象,pClients
- // 2、调用pClients->CreateClient(...)函数,参数1、2是要连接的服务端IP和端口,
- // 3服务端返回消息的事件回调处理函数,4是服务端断开连接的事件回调处理函数
- // 3、调用pClients->SendMsg(...)给对端发消息
- // 4、调用pClients->SendFile(...)给对端发文件
- // 5、调用pClients->Disconnet(...)主动断开连接
- // 6、销毁pClients对象
- //时间: 2010.5.1 23:13:56
- //作者: 废人
- //***********************************************************************************
- #include "stdafx.h"
- #include "TSocket.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- #pragma warning(disable:4800)
- DWORD WINAPI ServerWorkerProc(LPVOID lParam)
- {
- TClients* clientManager=(TClients*)lParam;
- HANDLE CompletionPort=clientManager->CompletionPort;
- DWORD ByteTransferred;
- LPPER_HANDLE_DATA PerHandleData;
- PPER_IO_OPERATION_DATA PerIoData;
- DWORD RecvByte;
- while(true)
- {
- bool bSuccess=GetQueuedCompletionStatus(CompletionPort,
- &ByteTransferred,
- (LPDWORD)&PerHandleData,
- (LPOVERLAPPED* )&PerIoData,
- INFINITE);
- //退出信号到达,退出线程
- if(ByteTransferred==-1 && PerIoData==NULL)
- {
- return 1L;
- }
- //客户机已经断开连接或者连接出现错误
- if(ByteTransferred==0 && (PerIoData->OperType==RECV_POSTED || PerIoData->OperType==SEND_POSTED))
- {
- //将该客户端数据删除
- ::EnterCriticalSection(&clientManager->cClientSection);
- clientManager->m_clients.erase(PerHandleData->client->m_Sock);
- ::LeaveCriticalSection(&clientManager->cClientSection);
- //记录退出日志
- clientManager->WriteLogString("Ip: %s,port:%d,Socket : %d Disconneted",PerHandleData->client->m_RemoteIP,
- PerHandleData->client->m_RemotePort,PerHandleData->client->m_Sock);
- TRACE("\nSocket : %d Disconneted",PerHandleData->client->m_Sock);
- //调用回调函数,通知上层该客户端已经断开
- PerHandleData->client->OnReceive(NULL,0);
- //关闭套接口
- closesocket(PerHandleData->client->m_Sock);
- GlobalFree(PerHandleData);
- GlobalFree(PerIoData);
- continue;
- }
- //为读操作完成,处理数据
- if(PerIoData->OperType==RECV_POSTED)
- {
- //调用回调函数,处理数据
- PerHandleData->client->OnReceive(PerIoData->RecvBuf,ByteTransferred);
- //将源数据置空
- memset(PerIoData->RecvBuf,0,BUFFER_SIZE);
- ByteTransferred=0;
- //重置IO操作数据
- unsigned long Flag=0;
- ZeroMemory(&(PerIoData->OverLapped),sizeof(OVERLAPPED));
- PerIoData->RecvDataBuf.buf=PerIoData->RecvBuf;
- PerIoData->RecvDataBuf.len=BUFFER_SIZE;
- PerIoData->OperType=RECV_POSTED;
- //提交另一个Recv请求
- WSARecv(PerHandleData->client->m_Sock,&(PerIoData->RecvDataBuf),1,&RecvByte,&Flag,&(PerIoData->OverLapped),NULL);
- }
- //发送完成,置空缓冲区,释放缓冲区
- if(PerIoData->OperType==SEND_POSTED)
- {
- memset(PerIoData,0,sizeof(PER_IO_OPERATION_DATA));
- GlobalFree(PerIoData);
- ByteTransferred=0;
- }
- }
- return 0L;
- }
- TClients::TClients(LPCTSTR strLogPath)
- {
- if (NULL==strLogPath||strlen(strLogPath)>=MAX_PATH)
- {
- strcpy(m_LogPath,"TClientsLog.log");
- }else
- {
- strcpy(m_LogPath,strLogPath);
- }
- InitNetWork();
- }
- TClients::~TClients()
- {
- UnInit();
- }
- void TClients::UnInit()
- {
- //1、关闭所有连接
- DisconnetAll();
- //2、退出工作线程
- SYSTEM_INFO sys_Info;
- GetSystemInfo(&sys_Info);
- for(int i=0;i<sys_Info.dwNumberOfProcessors*2+2;i++)
- {
- //寄出退出消息
- PostQueuedCompletionStatus(CompletionPort,-1,-1,NULL);
- }
- //3、删除所有的对象
- for (TSortClients::iterator it=m_clients.begin();it!=m_clients.end();it++)
- {
- delete it->second;
- }
- DeleteCriticalSection(&cClientSection);
- }
- void TClients::InitNetWork()
- {
- WSADATA wsaData;
- //1、Net Start Up
- WSAStartup(MAKEWORD(0x02,0x02),&wsaData);
- if(WSAStartup(MAKEWORD(0x02,0x02),&wsaData)!=0)WriteLogString("WSAStartUp Faild With Error: %d",WSAGetLastError());
- //2、创建完成端口
- CompletionPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
- if(CompletionPort==INVALID_HANDLE_VALUE)
- {
- WriteLogString("CreateIoCompletionPort faild with Error: %d",GetLastError());
- return;
- }
- //3、创建工作线程池
- SYSTEM_INFO sys_Info;
- GetSystemInfo(&sys_Info);
- for(int i=0;i<sys_Info.dwNumberOfProcessors*2+2;i++)
- {
- HANDLE ThreadHandle;
- DWORD ThreadID;
- ThreadHandle=CreateThread(NULL,0,ServerWorkerProc,this,0,&ThreadID);
- if(ThreadHandle==NULL)
- {
- WriteLogString("Create Server Work Thread faild with Error: %d",WSAGetLastError());
- return ;
- }
- CloseHandle(ThreadHandle);
- }
- InitializeCriticalSection(&cClientSection);
- }
- bool TClients::GetRemoteAddress(SOCKET sClient,char * IP,ULONG &port)
- {
- TClient *client=NULL;
- EnterCriticalSection(&cClientSection);
- TSortClients::iterator it=m_clients.find(sClient);
- if (it!=m_clients.end())
- {
- client=it->second;
- }
- LeaveCriticalSection(&cClientSection);
- if (!client)return false;
- strcpy(IP,client->m_RemoteIP);
- port=client->m_RemotePort;
- return true;
- }
- bool TClients::GetLocalIP(char *&IP)
- {
- char Name[100];
- hostent *pHostEntry;
- in_addr rAddr;
- if( 0 == gethostname ( Name, 100 ) )
- {
- pHostEntry = gethostbyname( Name );
- if( pHostEntry != NULL )
- {
- memcpy( &rAddr, pHostEntry->h_addr_list[0], sizeof(struct in_addr) );
- sprintf(IP,"%s",inet_ntoa( rAddr ));
- return true;
- }
- else
- {
- WriteLogString("GetHostIp faild with Error: %d",WSAGetLastError());
- }
- }
- return false;
- }
- SOCKET TClients::CreateClient(const char *pSerIp,ULONG iSvrPort,
- ProcessRecvData* OnProcessRecvData,ProcessPeerClose* OnProcessPeerClose)
- {
- int Error=0;
- //Socket Create
- SOCKET sock;
- if((sock=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
- {
- Error = WSAGetLastError();
- WriteLogString("WSASocket Faild With Error: %d",Error);
- return INVALID_SOCKET;
- }
- struct sockaddr_in inAddr;
- inAddr.sin_family=AF_INET;
- inAddr.sin_port=htons(iSvrPort);
- inAddr.sin_addr.S_un.S_addr=inet_addr(pSerIp);
- if (connect(sock,(PSOCKADDR)&inAddr,sizeof(inAddr))==SOCKET_ERROR )
- {
- Error=WSAGetLastError();
- WriteLogString("connect Server Socket Faild :%d",Error);
- return INVALID_SOCKET;
- }
- TClient *client=new TClient;
- client->m_ClientManager=this;
- client->m_pfPeerClose=OnProcessPeerClose;
- client->m_pfRecvData=OnProcessRecvData;
- strcpy(client->m_RemoteIP,pSerIp);
- client->m_RemotePort=iSvrPort;
- client->m_Sock=sock;
- //申请新的句柄操作数据
- LPPER_HANDLE_DATA PerHandleData=(LPPER_HANDLE_DATA) GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
- //句柄数据
- PerHandleData->client=client;
- //存储客户信息
- ::EnterCriticalSection(&cClientSection);
- m_clients[sock]=client;
- ::LeaveCriticalSection(&cClientSection);
- //转储信息
- WriteLogString("Ip: %s,port:%d,Socket : %d Conneted",client->m_RemoteIP,client->m_RemotePort,client->m_Sock);
- //关联客户端口到完成端口,句柄数据在此时被绑定到完成端口
- CreateIoCompletionPort((HANDLE)sock,CompletionPort,(DWORD)PerHandleData,0);
- //Io操作数据标志
- PPER_IO_OPERATION_DATA PerIoData=(PPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA));
- unsigned long Flag=0;
- DWORD RecvByte;
- ZeroMemory(&(PerIoData->OverLapped),sizeof(OVERLAPPED));
- PerIoData->RecvDataBuf.buf=PerIoData->RecvBuf;
- PerIoData->RecvDataBuf.len=BUFFER_SIZE;
- PerIoData->OperType=RECV_POSTED;
- //提交首个接收数据请求
- //这时
- //如果客户端断开连接
- //则也可以以接收数据时得到通知
- WSARecv(sock,&(PerIoData->RecvDataBuf),1,&RecvByte,&Flag,&(PerIoData->OverLapped),NULL);
- return sock;
- }
- void TClients::WriteLogString(const char *format,...)
- {
- char buf[1025]={0};
- try
- {
- SYSTEMTIME sysTm;
- ::GetLocalTime(&sysTm);
- sprintf(buf,"%d-%d-%d %d:%d:%d:%3d\t%s\n",sysTm.wYear,sysTm.wMonth,sysTm.wDay,sysTm.wHour,
- sysTm.wMinute,sysTm.wSecond,sysTm.wMilliseconds,buf);
- int len=strlen(buf);
- va_list arg;
- va_start(arg,format);
- _vsntprintf(buf+len,1024-len, format,arg);
- va_end(arg);
- FILE *fp=fopen(m_LogPath,"a");
- if (!fp)return;
- fwrite(buf,strlen(buf),1,fp);
- fclose(fp);
- }
- catch (...)
- {
- }
- }
- bool TClients::Disconnet(SOCKET sClient)
- {
- TClient *client=NULL;
- ::EnterCriticalSection(&cClientSection);
- TSortClients::iterator it=m_clients.find(sClient);
- if (it!=m_clients.end())
- {
- client=it->second;
- m_clients.erase(sClient);
- }
- ::LeaveCriticalSection(&cClientSection);
- if (client)
- {
- delete client;
- shutdown(sClient,1);
- return closesocket(sClient)==SOCKET_ERROR?false:true;
- }
- return false;
- }
- bool TClients::DisconnetAll()
- {
- ::EnterCriticalSection(&cClientSection);
- for (TSortClients::iterator it=m_clients.begin();it!=m_clients.end();it++)
- {
- shutdown(it->first,1);
- closesocket(it->first);
- delete it->second;
- }
- m_clients.clear();
- ::LeaveCriticalSection(&cClientSection);
- return true;
- }
- bool TClients::SendMsg(SOCKET sClient,char * pData,ULONG Length)
- {
- if (sClient==INVALID_SOCKET||pData==NULL||Length==0)return false;
- int head=0;
- ULONG packlen=BUFFER_SIZE-MinDataLen;
- if (Length>packlen)//需要分包
- {
- head=1;
- }
- //申请操作键
- PPER_IO_OPERATION_DATA PerIoData;
- ULONG left=Length;
- TData dat;
- while (left>0)
- {
- PerIoData=(PPER_IO_OPERATION_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA));
- //准备缓冲
- unsigned long Flag=0;
- DWORD SendByte;
- ZeroMemory(&(PerIoData->OverLapped),sizeof(OVERLAPPED));
- dat.data=PerIoData->SendBuf;
- if (0==head)
- {
- dat.AddType(0);
- dat.AddInt(Length);
- dat.AddData(pData,Length);
- left=0;
- }else if(1==head)
- {
- dat.AddType(1);
- dat.AddInt(Length);
- if (0==++Channel)Channel=1;
- dat.AddInt(Channel);
- dat.AddData(pData,BUFFER_SIZE-MinFileHeadLen);
- pData+=BUFFER_SIZE-MinFileHeadLen;
- head=2;
- left=Length-packlen;
- }else
- {
- dat.AddType(3);
- dat.AddInt(Channel);
- if (left>packlen)
- {
- dat.AddData(pData,packlen);
- left-=packlen;
- }else
- {
- dat.AddData(pData,left);
- left=0;
- }
- }
- PerIoData->SendDataBuf.buf=dat.data;
- PerIoData->SendDataBuf.len=dat.totalLen;
- PerIoData->OperType=SEND_POSTED;
- int bRet=WSASend(sClient,&(PerIoData->SendDataBuf),1,&SendByte,Flag,&(PerIoData->OverLapped),NULL);
- if(bRet==SOCKET_ERROR && GetLastError()!=WSA_IO_PENDING)
- {
- WriteLogString("WSASend With Error : %d",GetLastError());
- return false;
- }
- }
- return true;
- }
- /************************************************************************************************************/
- /************************************************************************************************************/
- TClient::TClient()
- {
- m_tempDta.data=new char[2*BUFFER_SIZE];
- m_tempDta.CurPack=m_tempDta.data;
- m_tempDta.totalLen=0;
- }
- TClient::~TClient()
- {
- clear();
- delete[] m_tempDta.data;
- }
- void TClient::clear()
- {
- for (TPacks::iterator it=m_Receivepacks.begin();it!=m_Receivepacks.end();it++)
- {
- delete[] it->second->data;
- delete it->second;
- }
- }
- void TClient::OnReceive(char *data,ULONG len)//data是一个全局指针
- {
- //1、已经断开连接
- if (0==len&&m_pfPeerClose)
- {
- m_pfPeerClose();
- clear();
- return;
- }
- //2、先处理以前遗留的数据,有数据就合起来
- lb1: if(m_tempDta.totalLen==0)//上面没有遗留数据,不用拷贝直接使用data指针
- {
- if (len<=MinDataLen)//两个数据包相加都不满足最小需求,继续等待
- {
- m_tempDta.AddData(data,len);
- return;
- }
- TData dat;
- dat.data=data;
- dat.totalLen=len;
- char type=dat.GetType();
- ULONG ilen=dat.GetInt();
- switch(type)
- {
- case 1:
- {
- ULONG Channel=dat.GetInt();
- if (0==Channel||len!=BUFFER_SIZE)//不足一帧,交由m_tempDta去等待
- {
- m_tempDta.AddData(data,len);
- return;
- }
- TPack *pack=new TPack;
- pack->data=new char[ilen];
- pack->CurPack=pack->data;
- pack->totalLen=ilen;
- pack->AddData(data+MinDataHeadLen,len-MinDataHeadLen);
- m_Receivepacks[Channel]=pack;
- break;
- }
- case 2:
- {
- break;
- }
- case 3:
- {
- TPack *pack=m_Receivepacks[ilen];
- ULONG curlen=pack->CurPack-pack->data;
- if (pack->totalLen==len-MinDataLen+curlen)//已经完成了数据包的接收
- {
- pack->AddData(data+MinDataHeadLen,len-MinDataHeadLen);
- m_pfRecvData(pack->data,pack->totalLen);
- delete[] pack->data;
- delete pack;
- m_Receivepacks.erase(ilen);
- }else if (pack->totalLen>len-MinDataLen+curlen)
- {
- if (len!=BUFFER_SIZE)//不满一帧,交由m_tempDta继续等待
- {
- m_tempDta.AddData(data,len);
- }else //满一帧,直接加入缓存
- {
- pack->AddData(data+MinDataHeadLen,len-MinDataHeadLen);
- }
- }else //已经满一帧,并附带了多余的其他帧
- {
- pack->AddData(data+MinDataHeadLen,pack->totalLen-curlen);
- m_pfRecvData(pack->data,pack->totalLen);
- ULONG tlen=MinDataHeadLen+pack->totalLen-curlen;
- data+=tlen;
- len-=tlen;
- delete[] pack->data;
- delete pack;
- m_Receivepacks.erase(ilen);
- goto lb1;//重新计算
- }
- break;
- }
- case 4:
- {
- break;
- }
- default:
- {
- ULONG tlen=MinDataLen+ilen;
- if (tlen==len)
- {
- m_pfRecvData(dat.Cur,ilen);
- }else if (tlen>len)
- {
- m_tempDta.AddData(data,len);
- }else
- {
- m_pfRecvData(dat.Cur,ilen);
- data+=tlen;
- len-=tlen;
- goto lb1;//重新计算
- }
- break;
- }
- }
- }else //上面有遗留数据,
- {
- m_tempDta.AddData(data,len);
- lb2: if (m_tempDta.totalLen<=MinDataLen)return;//两个数据包相加都不满足最小需求,继续等待
- TData dat;
- dat.data=m_tempDta.data;
- dat.totalLen=m_tempDta.totalLen;
- char type=dat.GetType();
- ULONG ilen=dat.GetInt();
- switch(type)
- {
- case 1:
- {
- ULONG Channel=dat.GetInt();
- if (0==Channel||m_tempDta.totalLen<BUFFER_SIZE)//一帧都不够,继续等待
- {
- return;
- }
- TPack *pack=new TPack;
- pack->data=new char[ilen];
- pack->CurPack=pack->data;
- pack->totalLen=ilen;
- pack->AddData(m_tempDta.data+MinDataHeadLen,BUFFER_SIZE-MinDataHeadLen);
- m_Receivepacks[Channel]=pack;
- if (m_tempDta.totalLen==BUFFER_SIZE)
- {
- m_tempDta.clear();
- }else
- {
- memcpy(m_tempDta.data,m_tempDta.data+BUFFER_SIZE,m_tempDta.totalLen-BUFFER_SIZE);
- m_tempDta.totalLen-=BUFFER_SIZE;
- goto lb2;//重新计算
- }
- break;
- }
- case 2:
- {
- break;
- }
- case 3:
- {
- TPack *pack=m_Receivepacks[ilen];
- ULONG curlen=pack->CurPack-pack->data;
- if (pack->totalLen==dat.totalLen-MinDataLen+curlen)//已经完成了数据包的接收
- {
- pack->AddData(dat.data+MinDataHeadLen,dat.totalLen-MinDataHeadLen);
- m_pfRecvData(pack->data,pack->totalLen);
- delete[] pack->data;
- delete pack;
- m_Receivepacks.erase(ilen);
- }else if (pack->totalLen>len-MinDataLen+curlen)
- {
- if (dat.totalLen==BUFFER_SIZE)//不满一帧,继续等待
- {
- pack->AddData(dat.data+MinDataHeadLen,len-MinDataHeadLen);
- m_tempDta.AddData(dat.data,dat.totalLen);
- }else if(dat.totalLen>BUFFER_SIZE) //满一帧,直接加入缓存
- {
- pack->AddData(dat.data+MinDataHeadLen,BUFFER_SIZE-MinDataHeadLen);
- memcpy(m_tempDta.data,dat.data+BUFFER_SIZE,dat.totalLen-BUFFER_SIZE);
- m_tempDta.totalLen-=BUFFER_SIZE;
- goto lb2;
- }
- }else
- {
- pack->AddData(dat.data+MinDataHeadLen,pack->totalLen-curlen);
- m_pfRecvData(pack->data,pack->totalLen);
- ULONG tlen=MinDataHeadLen+pack->totalLen-curlen;
- memcpy(m_tempDta.data,dat.data+tlen,dat.totalLen-tlen);
- data+=tlen;
- m_tempDta.totalLen-=tlen;
- delete[] pack->data;
- delete pack;
- m_Receivepacks.erase(ilen);
- goto lb2;//重新计算
- }
- break;
- }
- case 4:
- {
- break;
- }
- default:
- {
- ULONG tlen=MinDataLen+ilen;
- if (tlen==m_tempDta.totalLen)
- {
- m_pfRecvData(dat.Cur,ilen);
- m_tempDta.clear();
- }else if (tlen<m_tempDta.totalLen)
- {
- m_pfRecvData(dat.Cur,ilen);
- memcpy(m_tempDta.data,dat.Cur+ilen,m_tempDta.totalLen-tlen);
- m_tempDta.totalLen-=tlen;
- goto lb2;//重新计算
- }
- break;
- }
- }
- }
- }
- void TData::AddType(char type)
- {
- totalLen=cSize;
- memcpy(data,&type,totalLen);
- }
- void TData::AddInt(ULONG len)
- {
- memcpy(data+totalLen,&len,ULSize);
- totalLen+=ULSize;
- }
- void TData::AddData(char *buf,ULONG len)
- {
- int clen=len+totalLen>BUFFER_SIZE?BUFFER_SIZE-len:len;
- memcpy(data+totalLen,buf,clen);
- totalLen+=clen;
- }
- char TData::GetType()
- {
- char type;
- memcpy(&type,data,cSize);
- Cur=data+cSize;
- return type;
- }
- ULONG TData::GetInt()
- {
- if (Cur-data+ULSize>totalLen)return 0;
- ULONG l;
- memcpy(&l,Cur,ULSize);
- Cur+=ULSize;
- return l;
- }
- char* TData::GetData(ULONG &retlen)
- {
- retlen=totalLen-(ULONG)(Cur-data);
- return Cur;
- }
- </pre><br>
- <br>
- <pre></pre>
- <p><br>
- </p>