client

[cpp]  view plain  copy
 print ?
  1. //***********************************************************************************  
  2. //文件说明:TSocket.h  
  3. //功能:   文件传输客户端实现头文件  
  4. //使用说明:使用TCP的IOCP实现,可以传送大消息包、文件,同一客户端可以同时发送多个文件  
  5. //          1、用TClients创建一个对象,pClients  
  6. //          2、调用pClients->CreateClient(...)函数,参数1、2是要连接的服务端IP和端口,  
  7. //             3服务端返回消息的事件回调处理函数,4是服务端断开连接的事件回调处理函数  
  8. //          3、调用pClients->SendMsg(...)给对端发消息  
  9. //          4、调用pClients->SendFile(...)给对端发文件  
  10. //          5、调用pClients->Disconnet(...)主动断开连接  
  11. //          6、销毁pClients对象  
  12. //时间:   2010.5.1 23:13:56  
  13. //作者:   废人  
  14. //留待实现:  
  15. // bool SendFileToAll(const char * filename);  
  16. // bool SendFileToServers(SOCKETS sClients,const char * filename);    
  17. // bool SendFileToOther(SOCKET ExceptSocket,char * pData,ULONG Length);  
  18. // bool SendMsgToAll(char * pData,ULONG Length);  
  19. // bool SendMsgToServers(SOCKETS sClients,char * pData,ULONG Length);     
  20. // bool SendMsgToOther(SOCKET ExceptSocket,char * pData,ULONG Length);  
  21. //***********************************************************************************  
  22.   
  23. #if !defined(AFX_TSOCKET_H__46FFF420_23C3_4356_A88D_AEBDA61EA186__INCLUDED_)  
  24. #define AFX_TSOCKET_H__46FFF420_23C3_4356_A88D_AEBDA61EA186__INCLUDED_  
  25.   
  26. #if _MSC_VER > 1000  
  27. #pragma once  
  28. #endif // _MSC_VER > 1000  
  29.   
  30. #include <list>  
  31. #include <afxtempl.h>  
  32.   
  33. #include <winsock2.h>  
  34. #include <vector>  
  35. #include <queue>  
  36. #include <string>  
  37. #include <algorithm>  
  38. #include <map>  
  39. #pragma  comment(lib,"ws2_32.lib")  
  40.   
  41. using namespace std;  
  42. #pragma  warning(disable:4786)  
  43. //服务端口  
  44. #define SVRPORT 10012  
  45. //缓冲区大小  
  46. #define BUFFER_SIZE 4096  
  47. //接收数据  
  48. #define RECV_POSTED 0  
  49. //发送数据  
  50. #define SEND_POSTED 1  
  51.   
  52. class TClient;  
  53. class TClients;  
  54. struct TPack;  
  55. //单句柄数据  
  56. typedef struct _PER_HANDLE_DATA  
  57. {  
  58.     TClient *client;  
  59. }PER_HANDLE_DATA,*LPPER_HANDLE_DATA;  
  60. //IO操作数据  
  61. typedef struct _PER_IO_OPERATION_DATA  
  62. {  
  63.     //重叠结构  
  64.     OVERLAPPED OverLapped;  
  65.     //数据缓冲区  
  66.     WSABUF RecvDataBuf;  
  67.     WSABUF SendDataBuf;  
  68.     char RecvBuf[BUFFER_SIZE];  
  69.     char SendBuf[BUFFER_SIZE];  
  70.     //操作类型表示  
  71.     bool OperType;  
  72. }PER_IO_OPERATION_DATA,*PPER_IO_OPERATION_DATA;  
  73.   
  74. typedef map<SOCKET,TClient*> TSortClients; //排序的客户端  
  75. typedef map<ULONG,TPack *> TPacks;           //有些数据包需要重组才能合成大数据包回调ProcessRecvData函数,占时保存结构  
  76. typedef vector<SOCKET> SOCKETS;  
  77.   
  78. //回调处理数据函数原型  
  79. typedef void __stdcall ProcessRecvData(char * pData,ULONG DataLength);  
  80. typedef void __stdcall ProcessPeerClose();  
  81. typedef void __stdcall ProcessFileTransfer(char *filename,double speed);  
  82. DWORD WINAPI ServerWorkerProc(LPVOID lParam);   //工作线程  
  83. DWORD WINAPI ListenProc(LPVOID lParam);  
  84.   
  85. ULONG ULSize=sizeof(ULONG);  
  86. ULONG cSize=sizeof(char);  
  87. class TData  
  88. {  
  89. public:  
  90.     char *data;   
  91.     ULONG totalLen;  
  92.     char *Cur;  
  93.     void AddType(char type);  
  94.     void AddInt(ULONG len);  
  95.     void AddData(char *buf,ULONG len);    
  96.     char GetType();  
  97.     ULONG GetInt();  
  98.     char* GetData(ULONG &retlen);  
  99. };  
  100. struct TPack  
  101. {  
  102.     char *data;  
  103.     char *CurPack;  
  104.     ULONG totalLen;  
  105.     void clear()  
  106.     {  
  107.         CurPack=data;  
  108.         totalLen=0;  
  109.     }  
  110.     void AddData(char*d,ULONG len)  
  111.     {  
  112.         memcpy(CurPack,d,len);  
  113.         CurPack+=len;  
  114.         totalLen+=len;  
  115.     }  
  116. };  
  117.   
  118. struct TDataMod //用于传输的模型,用malloc和free,大小不超过BUFFER_SIZE  
  119. {  
  120.     char type;  //0单独数据包,1连续消息数据包头,2文件数据包头,3连续包的消息体,4文件包的消息体,5是否需要销毁本指针  
  121.     ULONG Len;  
  122.     ULONG Channel;   
  123.     char data;  
  124.     //1、连续消息第一个包的 Len是长度,Channel是Send的传输号,以后Len就是Send的传输号  
  125.     //2、文件消息第一个包的 Len是长度,Channel是Send的传输号,以后Len就是Send的传输号  
  126.     //3、单独包是只有Len长度,Index是数据内容    
  127. };  
  128.   
  129. struct TFileDataHead  
  130. {  
  131.     char type;    
  132.     ULONG Channel;   
  133.     TCHAR       szFileTitle[128];                   //文件的标题名  
  134.     DWORD       dwFileAttributes;                   //文件的属性  
  135.     FILETIME    ftCreationTime;                     //文件的创建时间  
  136.     FILETIME    ftLastAccessTime;                   //文件的最后访问时间  
  137.     FILETIME    ftLastWriteTime;                    //文件的最后修改时间  
  138.     DWORD       nFileSizeHigh;                      //文件大小的高位双字  
  139.     DWORD       nFileSizeLow;                       //文件大小的低位双字  
  140.     DWORD       dwReserved0;                        //保留,为0  
  141.     DWORD       dwReserved1;                        //保留,为0  
  142.     TCHAR       cAlternateFileName;   
  143.     TCHAR       cFileName;  
  144. };  
  145.   
  146. //消息包的类型:  
  147. //1、单独数据包(TData),type==0,Len为长度,data开始存储的是数据 (MinDataLen)  
  148. //2、连续消息数据包头,type==1,Len为消息体总长度,Channel是当前通道号,data信息数据(MinDataHeadLen)  
  149. //3、连续消息中间数据包,type==3,Len为Channel号,data信息数据(MinDataLen)  
  150. //4、文件头TFileDataHead,type==2  
  151. //5、文件中间数据包,type==4,Len为Channel号,data信息数据(MinDataLen)  
  152.   
  153. ULONG MinDataLen=ULSize+cSize;  
  154. ULONG MinDataHeadLen=MinDataLen+ULSize;  
  155. ULONG MinFileHeadLen=sizeof(TFileDataHead);  
  156.   
  157.   
  158. class TClient   //用于中间实现的类,不能直接使用  
  159. {  
  160. public:  
  161.     TClient();  
  162.     ~TClient();  
  163.     void OnReceive(char *data,ULONG len);//data是一个全局指针  
  164. private:  
  165.     void clear();  
  166.     ProcessPeerClose *m_pfPeerClose;  
  167.     //客户端消息回调函数  
  168.     ProcessRecvData *m_pfRecvData;  
  169.     //本端管理者指针  
  170.     TClients *m_ClientManager;  
  171.     //临时存放分块数据包进行组装  
  172.     TPacks m_Receivepacks;  
  173.     //本端的SOCKET号  
  174.     SOCKET m_Sock;  
  175.     //对端的IP  
  176.     char m_RemoteIP[16];  
  177.     //对端的端口  
  178.     ULONG m_RemotePort;  
  179.     //临时存放不足一帧的数据  
  180.     TPack m_tempDta;      
  181.     friend DWORD WINAPI ServerWorkerProc(LPVOID lParam);  
  182.     friend class TClients;  
  183. };  
  184.   
  185. class TClients  //外部接口类,可以用其公有方法接口  
  186. {  
  187. public:  
  188.     TClients(LPCTSTR strLogPath="TClientsLog.log");  
  189.     ~TClients();  
  190.     SOCKET CreateClient(const char *pSerIp,ULONG iSvrPort=SVRPORT,  
  191.                         ProcessRecvData* OnProcessRecvData=NULL,ProcessPeerClose* OnProcessPeerClose=NULL);  
  192.     bool Disconnet(SOCKET sClient);  
  193.     bool DisconnetAll();  
  194.     bool SendMsg(SOCKET sClient,char * pData,ULONG Length);  
  195.     bool SendFile(SOCKET sClient,const char * filename,ProcessFileTransfer *OnFileTrans=NULL){return true;}  
  196.     bool GetRemoteAddress(SOCKET sClient,char * IP,ULONG &port);  
  197.     bool GetLocalIP(char *&IP);  
  198.       
  199. private:  
  200.     //完成句柄  
  201.     HANDLE CompletionPort;  
  202.     //客户信息临界保护量  
  203.     CRITICAL_SECTION cClientSection;  
  204.     //当前发送的通道号  
  205.     ULONG Channel;  
  206.     //客户信息列表  
  207.     TSortClients m_clients;   
  208.     //写日志文件  
  209.     char m_LogPath[MAX_PATH];  
  210.     void WriteLogString(const char *format,...);  
  211.     void InitNetWork();  
  212.     void UnInit();  
  213. private:  
  214.     friend class TClient;  
  215.     friend DWORD WINAPI ServerWorkerProc(LPVOID lParam);  
  216. };  
  217.   
  218.   
  219. #endif // !defined(AFX_TSOCKET_H__46FFF420_23C3_4356_A88D_AEBDA61EA186__INCLUDED_)  
[cpp]  view plain  copy
 print ?
  1.   
[cpp]  view plain  copy
 print ?
  1.   
[cpp]  view plain  copy
 print ?
  1. <pre name="code" class="cpp">//***********************************************************************************  
  2. //文件说明:TSocket.cpp  
  3. //功能:   文件传输客户端实现头文件  
  4. //使用说明:使用TCP的IOCP实现,可以传送大消息包、文件,线程安全同一客户端可以同时发送消息、文件  
  5. //          1、用TClients创建一个对象,pClients  
  6. //          2、调用pClients->CreateClient(...)函数,参数1、2是要连接的服务端IP和端口,  
  7. //             3服务端返回消息的事件回调处理函数,4是服务端断开连接的事件回调处理函数  
  8. //          3、调用pClients->SendMsg(...)给对端发消息  
  9. //          4、调用pClients->SendFile(...)给对端发文件  
  10. //          5、调用pClients->Disconnet(...)主动断开连接  
  11. //          6、销毁pClients对象  
  12. //时间:   2010.5.1 23:13:56  
  13. //作者:   废人  
  14. //***********************************************************************************  
  15. #include "stdafx.h"  
  16. #include "TSocket.h"  
  17.   
  18. #ifdef _DEBUG  
  19. #undef THIS_FILE  
  20. static char THIS_FILE[]=__FILE__;  
  21. #define new DEBUG_NEW  
  22. #endif  
  23.   
  24. #pragma  warning(disable:4800)  
  25.   
  26.   
  27. DWORD WINAPI ServerWorkerProc(LPVOID lParam)  
  28. {  
  29.     TClients* clientManager=(TClients*)lParam;  
  30.     HANDLE CompletionPort=clientManager->CompletionPort;  
  31.     DWORD ByteTransferred;  
  32.     LPPER_HANDLE_DATA PerHandleData;  
  33.     PPER_IO_OPERATION_DATA PerIoData;  
  34.     DWORD RecvByte;  
  35.     while(true)  
  36.     {  
  37.         bool bSuccess=GetQueuedCompletionStatus(CompletionPort,  
  38.                                                 &ByteTransferred,  
  39.                                                 (LPDWORD)&PerHandleData,  
  40.                                                 (LPOVERLAPPED* )&PerIoData,  
  41.                                                 INFINITE);  
  42.         //退出信号到达,退出线程  
  43.         if(ByteTransferred==-1 && PerIoData==NULL)  
  44.         {  
  45.             return 1L;  
  46.         }  
  47.         //客户机已经断开连接或者连接出现错误  
  48.         if(ByteTransferred==0 && (PerIoData->OperType==RECV_POSTED || PerIoData->OperType==SEND_POSTED))  
  49.         {  
  50.             //将该客户端数据删除           
  51.             ::EnterCriticalSection(&clientManager->cClientSection);  
  52.             clientManager->m_clients.erase(PerHandleData->client->m_Sock);  
  53.             ::LeaveCriticalSection(&clientManager->cClientSection);  
  54.             //记录退出日志  
  55.             clientManager->WriteLogString("Ip: %s,port:%d,Socket : %d Disconneted",PerHandleData->client->m_RemoteIP,  
  56.                                           PerHandleData->client->m_RemotePort,PerHandleData->client->m_Sock);  
  57.             TRACE("\nSocket : %d Disconneted",PerHandleData->client->m_Sock);  
  58.             //调用回调函数,通知上层该客户端已经断开  
  59.             PerHandleData->client->OnReceive(NULL,0);  
  60.             //关闭套接口  
  61.             closesocket(PerHandleData->client->m_Sock);  
  62.             GlobalFree(PerHandleData);  
  63.             GlobalFree(PerIoData);  
  64.             continue;  
  65.         }  
  66.         //为读操作完成,处理数据  
  67.         if(PerIoData->OperType==RECV_POSTED)  
  68.         {  
  69.             //调用回调函数,处理数据  
  70.             PerHandleData->client->OnReceive(PerIoData->RecvBuf,ByteTransferred);  
  71.             //将源数据置空  
  72.             memset(PerIoData->RecvBuf,0,BUFFER_SIZE);  
  73.             ByteTransferred=0;  
  74.             //重置IO操作数据  
  75.             unsigned long Flag=0;  
  76.             ZeroMemory(&(PerIoData->OverLapped),sizeof(OVERLAPPED));           
  77.             PerIoData->RecvDataBuf.buf=PerIoData->RecvBuf;  
  78.             PerIoData->RecvDataBuf.len=BUFFER_SIZE;  
  79.             PerIoData->OperType=RECV_POSTED;  
  80.             //提交另一个Recv请求  
  81.             WSARecv(PerHandleData->client->m_Sock,&(PerIoData->RecvDataBuf),1,&RecvByte,&Flag,&(PerIoData->OverLapped),NULL);  
  82.         }  
  83.         //发送完成,置空缓冲区,释放缓冲区  
  84.         if(PerIoData->OperType==SEND_POSTED)  
  85.         {  
  86.             memset(PerIoData,0,sizeof(PER_IO_OPERATION_DATA));  
  87.             GlobalFree(PerIoData);  
  88.             ByteTransferred=0;  
  89.         }  
  90.     }  
  91.     return 0L;  
  92. }  
  93.   
  94.   
  95. TClients::TClients(LPCTSTR strLogPath)  
  96. {     
  97.     if (NULL==strLogPath||strlen(strLogPath)>=MAX_PATH)  
  98.     {  
  99.         strcpy(m_LogPath,"TClientsLog.log");  
  100.     }else  
  101.     {  
  102.         strcpy(m_LogPath,strLogPath);  
  103.     }     
  104.     InitNetWork();  
  105. }  
  106. TClients::~TClients()  
  107. {  
  108.     UnInit();     
  109. }  
  110. void TClients::UnInit()  
  111. {  
  112.     //1、关闭所有连接  
  113.     DisconnetAll();  
  114.     //2、退出工作线程  
  115.     SYSTEM_INFO sys_Info;  
  116.     GetSystemInfo(&sys_Info);  
  117.     for(int i=0;i<sys_Info.dwNumberOfProcessors*2+2;i++)  
  118.     {  
  119.         //寄出退出消息  
  120.         PostQueuedCompletionStatus(CompletionPort,-1,-1,NULL);  
  121.     }  
  122.       
  123.     //3、删除所有的对象  
  124.     for (TSortClients::iterator it=m_clients.begin();it!=m_clients.end();it++)  
  125.     {  
  126.         delete it->second;  
  127.     }         
  128.     DeleteCriticalSection(&cClientSection);  
  129. }  
  130. void TClients::InitNetWork()  
  131. {  
  132.     WSADATA wsaData;  
  133.     //1、Net Start Up  
  134.     WSAStartup(MAKEWORD(0x02,0x02),&wsaData);  
  135.     if(WSAStartup(MAKEWORD(0x02,0x02),&wsaData)!=0)WriteLogString("WSAStartUp Faild With Error: %d",WSAGetLastError());  
  136.     //2、创建完成端口  
  137.     CompletionPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);  
  138.     if(CompletionPort==INVALID_HANDLE_VALUE)  
  139.     {  
  140.         WriteLogString("CreateIoCompletionPort faild with Error: %d",GetLastError());  
  141.         return;  
  142.     }  
  143.     //3、创建工作线程池  
  144.     SYSTEM_INFO sys_Info;  
  145.     GetSystemInfo(&sys_Info);  
  146.     for(int i=0;i<sys_Info.dwNumberOfProcessors*2+2;i++)  
  147.     {  
  148.         HANDLE ThreadHandle;  
  149.         DWORD ThreadID;  
  150.           
  151.         ThreadHandle=CreateThread(NULL,0,ServerWorkerProc,this,0,&ThreadID);  
  152.         if(ThreadHandle==NULL)  
  153.         {  
  154.             WriteLogString("Create Server Work Thread faild with Error: %d",WSAGetLastError());  
  155.             return ;  
  156.         }     
  157.         CloseHandle(ThreadHandle);  
  158.     }  
  159.     InitializeCriticalSection(&cClientSection);   
  160. }  
  161. bool TClients::GetRemoteAddress(SOCKET sClient,char * IP,ULONG &port)  
  162. {  
  163.     TClient *client=NULL;  
  164.     EnterCriticalSection(&cClientSection);  
  165.     TSortClients::iterator it=m_clients.find(sClient);  
  166.     if (it!=m_clients.end())  
  167.     {  
  168.         client=it->second;  
  169.     }  
  170.     LeaveCriticalSection(&cClientSection);  
  171.     if (!client)return false;  
  172.     strcpy(IP,client->m_RemoteIP);  
  173.     port=client->m_RemotePort;  
  174.     return true;  
  175. }  
  176. bool TClients::GetLocalIP(char *&IP)  
  177. {  
  178.     char Name[100];  
  179.     hostent *pHostEntry;  
  180.     in_addr rAddr;  
  181.     if( 0 == gethostname ( Name, 100 ) )  
  182.     {  
  183.         pHostEntry = gethostbyname( Name );  
  184.         if( pHostEntry != NULL )  
  185.         {  
  186.             memcpy( &rAddr, pHostEntry->h_addr_list[0], sizeof(struct in_addr) );  
  187.             sprintf(IP,"%s",inet_ntoa( rAddr ));  
  188.             return true;  
  189.         }  
  190.         else  
  191.         {  
  192.             WriteLogString("GetHostIp faild with Error: %d",WSAGetLastError());               
  193.         }  
  194.     }  
  195.     return false;  
  196. }  
  197. SOCKET TClients::CreateClient(const char *pSerIp,ULONG iSvrPort,  
  198.                     ProcessRecvData* OnProcessRecvData,ProcessPeerClose* OnProcessPeerClose)  
  199. {     
  200.     int Error=0;  
  201.     //Socket Create  
  202.     SOCKET sock;  
  203.     if((sock=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)  
  204.     {  
  205.         Error = WSAGetLastError();  
  206.         WriteLogString("WSASocket Faild With Error: %d",Error);  
  207.         return INVALID_SOCKET;  
  208.     }  
  209.       
  210.     struct sockaddr_in inAddr;  
  211.     inAddr.sin_family=AF_INET;  
  212.     inAddr.sin_port=htons(iSvrPort);  
  213.     inAddr.sin_addr.S_un.S_addr=inet_addr(pSerIp);  
  214.     if (connect(sock,(PSOCKADDR)&inAddr,sizeof(inAddr))==SOCKET_ERROR )  
  215.     {  
  216.         Error=WSAGetLastError();  
  217.         WriteLogString("connect Server Socket Faild :%d",Error);  
  218.         return INVALID_SOCKET;            
  219.     }  
  220.     TClient *client=new TClient;  
  221.     client->m_ClientManager=this;  
  222.     client->m_pfPeerClose=OnProcessPeerClose;  
  223.     client->m_pfRecvData=OnProcessRecvData;  
  224.     strcpy(client->m_RemoteIP,pSerIp);  
  225.     client->m_RemotePort=iSvrPort;  
  226.     client->m_Sock=sock;  
  227.     //申请新的句柄操作数据          
  228.     LPPER_HANDLE_DATA PerHandleData=(LPPER_HANDLE_DATA) GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));  
  229.     //句柄数据  
  230.     PerHandleData->client=client;          
  231.     //存储客户信息  
  232.     ::EnterCriticalSection(&cClientSection);  
  233.     m_clients[sock]=client;  
  234.     ::LeaveCriticalSection(&cClientSection);  
  235.     //转储信息  
  236.     WriteLogString("Ip: %s,port:%d,Socket : %d Conneted",client->m_RemoteIP,client->m_RemotePort,client->m_Sock);  
  237.     //关联客户端口到完成端口,句柄数据在此时被绑定到完成端口  
  238.     CreateIoCompletionPort((HANDLE)sock,CompletionPort,(DWORD)PerHandleData,0);  
  239.     //Io操作数据标志  
  240.       
  241.     PPER_IO_OPERATION_DATA PerIoData=(PPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA));  
  242.     unsigned long  Flag=0;  
  243.     DWORD RecvByte;  
  244.     ZeroMemory(&(PerIoData->OverLapped),sizeof(OVERLAPPED));  
  245.       
  246.     PerIoData->RecvDataBuf.buf=PerIoData->RecvBuf;  
  247.     PerIoData->RecvDataBuf.len=BUFFER_SIZE;  
  248.     PerIoData->OperType=RECV_POSTED;  
  249.     //提交首个接收数据请求  
  250.     //这时  
  251.     //如果客户端断开连接  
  252.     //则也可以以接收数据时得到通知      
  253.     WSARecv(sock,&(PerIoData->RecvDataBuf),1,&RecvByte,&Flag,&(PerIoData->OverLapped),NULL);  
  254.     return sock;  
  255. }  
  256. void TClients::WriteLogString(const char *format,...)  
  257. {  
  258.     char buf[1025]={0};  
  259.     try  
  260.     {  
  261.         SYSTEMTIME sysTm;  
  262.         ::GetLocalTime(&sysTm);  
  263.         sprintf(buf,"%d-%d-%d %d:%d:%d:%3d\t%s\n",sysTm.wYear,sysTm.wMonth,sysTm.wDay,sysTm.wHour,  
  264.                 sysTm.wMinute,sysTm.wSecond,sysTm.wMilliseconds,buf);  
  265.         int len=strlen(buf);  
  266.         va_list arg;  
  267.         va_start(arg,format);  
  268.         _vsntprintf(buf+len,1024-len, format,arg);        
  269.         va_end(arg);              
  270.         FILE *fp=fopen(m_LogPath,"a");  
  271.         if (!fp)return;  
  272.         fwrite(buf,strlen(buf),1,fp);  
  273.         fclose(fp);  
  274.     }  
  275.     catch (...)  
  276.     {         
  277.     }  
  278. }  
  279.   
  280. bool TClients::Disconnet(SOCKET sClient)  
  281. {  
  282.     TClient *client=NULL;  
  283.     ::EnterCriticalSection(&cClientSection);  
  284.     TSortClients::iterator it=m_clients.find(sClient);  
  285.     if (it!=m_clients.end())  
  286.     {  
  287.         client=it->second;  
  288.         m_clients.erase(sClient);  
  289.     }     
  290.     ::LeaveCriticalSection(&cClientSection);  
  291.     if (client)  
  292.     {  
  293.         delete client;  
  294.         shutdown(sClient,1);  
  295.         return closesocket(sClient)==SOCKET_ERROR?false:true;  
  296.     }  
  297.     return false;     
  298. }  
  299. bool TClients::DisconnetAll()  
  300. {  
  301.     ::EnterCriticalSection(&cClientSection);  
  302.     for (TSortClients::iterator it=m_clients.begin();it!=m_clients.end();it++)  
  303.     {  
  304.         shutdown(it->first,1);  
  305.         closesocket(it->first);  
  306.         delete it->second;  
  307.     }  
  308.     m_clients.clear();  
  309.     ::LeaveCriticalSection(&cClientSection);  
  310.     return true;  
  311. }  
  312. bool TClients::SendMsg(SOCKET sClient,char * pData,ULONG Length)  
  313. {  
  314.     if (sClient==INVALID_SOCKET||pData==NULL||Length==0)return false;  
  315.     int head=0;  
  316.     ULONG packlen=BUFFER_SIZE-MinDataLen;  
  317.     if (Length>packlen)//需要分包  
  318.     {  
  319.         head=1;  
  320.     }  
  321.     //申请操作键  
  322.     PPER_IO_OPERATION_DATA PerIoData;  
  323.     ULONG left=Length;    
  324.     TData dat;  
  325.     while (left>0)  
  326.     {  
  327.         PerIoData=(PPER_IO_OPERATION_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA));        
  328.         //准备缓冲  
  329.         unsigned long  Flag=0;  
  330.         DWORD SendByte;  
  331.         ZeroMemory(&(PerIoData->OverLapped),sizeof(OVERLAPPED));       
  332.         dat.data=PerIoData->SendBuf;   
  333.         if (0==head)  
  334.         {  
  335.             dat.AddType(0);  
  336.             dat.AddInt(Length);  
  337.             dat.AddData(pData,Length);    
  338.             left=0;  
  339.         }else if(1==head)  
  340.         {  
  341.             dat.AddType(1);  
  342.             dat.AddInt(Length);  
  343.             if (0==++Channel)Channel=1;  
  344.             dat.AddInt(Channel);              
  345.             dat.AddData(pData,BUFFER_SIZE-MinFileHeadLen);    
  346.             pData+=BUFFER_SIZE-MinFileHeadLen;  
  347.             head=2;  
  348.             left=Length-packlen;  
  349.         }else   
  350.         {  
  351.             dat.AddType(3);  
  352.             dat.AddInt(Channel);  
  353.             if (left>packlen)  
  354.             {  
  355.                 dat.AddData(pData,packlen);  
  356.                 left-=packlen;  
  357.             }else  
  358.             {  
  359.                 dat.AddData(pData,left);  
  360.                 left=0;  
  361.             }  
  362.         }             
  363.         PerIoData->SendDataBuf.buf=dat.data;  
  364.         PerIoData->SendDataBuf.len=dat.totalLen;  
  365.         PerIoData->OperType=SEND_POSTED;  
  366.         int bRet=WSASend(sClient,&(PerIoData->SendDataBuf),1,&SendByte,Flag,&(PerIoData->OverLapped),NULL);  
  367.         if(bRet==SOCKET_ERROR && GetLastError()!=WSA_IO_PENDING)  
  368.         {  
  369.             WriteLogString("WSASend With Error : %d",GetLastError());  
  370.             return false;  
  371.         }  
  372.       
  373.     }  
  374.     return true;  
  375. }  
  376.   
  377.   
  378.   
  379. /************************************************************************************************************/  
  380. /************************************************************************************************************/  
  381.   
  382.   
  383. TClient::TClient()  
  384. {  
  385.     m_tempDta.data=new char[2*BUFFER_SIZE];  
  386.     m_tempDta.CurPack=m_tempDta.data;  
  387.     m_tempDta.totalLen=0;  
  388. }  
  389. TClient::~TClient()  
  390. {  
  391.     clear();  
  392.     delete[] m_tempDta.data;  
  393. }  
  394. void TClient::clear()  
  395. {  
  396.     for (TPacks::iterator it=m_Receivepacks.begin();it!=m_Receivepacks.end();it++)  
  397.     {  
  398.         delete[] it->second->data;  
  399.         delete it->second;  
  400.     }         
  401. }  
  402. void TClient::OnReceive(char *data,ULONG len)//data是一个全局指针  
  403. {  
  404.     //1、已经断开连接  
  405.     if (0==len&&m_pfPeerClose)  
  406.     {  
  407.         m_pfPeerClose();  
  408.         clear();  
  409.         return;  
  410.     }  
  411.     //2、先处理以前遗留的数据,有数据就合起来  
  412.   
  413. lb1:    if(m_tempDta.totalLen==0)//上面没有遗留数据,不用拷贝直接使用data指针  
  414.     {  
  415.         if (len<=MinDataLen)//两个数据包相加都不满足最小需求,继续等待  
  416.         {  
  417.             m_tempDta.AddData(data,len);  
  418.             return;  
  419.         }  
  420.         TData dat;  
  421.         dat.data=data;  
  422.         dat.totalLen=len;  
  423.         char type=dat.GetType();  
  424.         ULONG ilen=dat.GetInt();  
  425.         switch(type)  
  426.         {  
  427.         case 1:  
  428.             {     
  429.                 ULONG Channel=dat.GetInt();  
  430.                 if (0==Channel||len!=BUFFER_SIZE)//不足一帧,交由m_tempDta去等待  
  431.                 {  
  432.                     m_tempDta.AddData(data,len);  
  433.                     return;  
  434.                 }  
  435.                 TPack *pack=new TPack;  
  436.                 pack->data=new char[ilen];  
  437.                 pack->CurPack=pack->data;  
  438.                 pack->totalLen=ilen;                   
  439.                 pack->AddData(data+MinDataHeadLen,len-MinDataHeadLen);             
  440.                 m_Receivepacks[Channel]=pack;  
  441.                 break;  
  442.             }  
  443.         case 2:  
  444.             {  
  445.                 break;  
  446.             }  
  447.         case 3:  
  448.             {  
  449.                 TPack *pack=m_Receivepacks[ilen];  
  450.                 ULONG curlen=pack->CurPack-pack->data;  
  451.                 if (pack->totalLen==len-MinDataLen+curlen)//已经完成了数据包的接收  
  452.                 {  
  453.                     pack->AddData(data+MinDataHeadLen,len-MinDataHeadLen);     
  454.                     m_pfRecvData(pack->data,pack->totalLen);  
  455.                     delete[] pack->data;  
  456.                     delete pack;  
  457.                     m_Receivepacks.erase(ilen);  
  458.                 }else if (pack->totalLen>len-MinDataLen+curlen)  
  459.                 {  
  460.                     if (len!=BUFFER_SIZE)//不满一帧,交由m_tempDta继续等待  
  461.                     {  
  462.                         m_tempDta.AddData(data,len);  
  463.                     }else                //满一帧,直接加入缓存  
  464.                     {  
  465.                         pack->AddData(data+MinDataHeadLen,len-MinDataHeadLen);     
  466.                     }  
  467.                 }else                    //已经满一帧,并附带了多余的其他帧  
  468.                 {  
  469.                     pack->AddData(data+MinDataHeadLen,pack->totalLen-curlen);   
  470.                     m_pfRecvData(pack->data,pack->totalLen);  
  471.                     ULONG tlen=MinDataHeadLen+pack->totalLen-curlen;  
  472.                     data+=tlen;  
  473.                     len-=tlen;  
  474.                     delete[] pack->data;  
  475.                     delete pack;  
  476.                     m_Receivepacks.erase(ilen);  
  477.                     goto lb1;//重新计算  
  478.                 }  
  479.                 break;  
  480.             }  
  481.         case 4:  
  482.             {  
  483.                 break;  
  484.             }  
  485.         default:  
  486.             {                     
  487.                 ULONG tlen=MinDataLen+ilen;  
  488.                 if (tlen==len)  
  489.                 {  
  490.                     m_pfRecvData(dat.Cur,ilen);  
  491.                 }else if (tlen>len)  
  492.                 {  
  493.                     m_tempDta.AddData(data,len);                          
  494.                 }else   
  495.                 {  
  496.                     m_pfRecvData(dat.Cur,ilen);  
  497.                     data+=tlen;  
  498.                     len-=tlen;  
  499.                     goto lb1;//重新计算  
  500.                 }                     
  501.                 break;  
  502.             }  
  503.         }  
  504.     }else                   //上面有遗留数据,  
  505.     {  
  506.         m_tempDta.AddData(data,len);  
  507. lb2:        if (m_tempDta.totalLen<=MinDataLen)return;//两个数据包相加都不满足最小需求,继续等待  
  508.         TData dat;  
  509.         dat.data=m_tempDta.data;  
  510.         dat.totalLen=m_tempDta.totalLen;  
  511.         char type=dat.GetType();  
  512.         ULONG ilen=dat.GetInt();  
  513.         switch(type)  
  514.         {  
  515.         case 1:  
  516.             {     
  517.                 ULONG Channel=dat.GetInt();  
  518.                 if (0==Channel||m_tempDta.totalLen<BUFFER_SIZE)//一帧都不够,继续等待  
  519.                 {                         
  520.                     return;  
  521.                 }  
  522.                 TPack *pack=new TPack;  
  523.                 pack->data=new char[ilen];  
  524.                 pack->CurPack=pack->data;  
  525.                 pack->totalLen=ilen;                   
  526.                 pack->AddData(m_tempDta.data+MinDataHeadLen,BUFFER_SIZE-MinDataHeadLen);           
  527.                 m_Receivepacks[Channel]=pack;  
  528.                 if (m_tempDta.totalLen==BUFFER_SIZE)  
  529.                 {  
  530.                     m_tempDta.clear();  
  531.                 }else  
  532.                 {  
  533.                     memcpy(m_tempDta.data,m_tempDta.data+BUFFER_SIZE,m_tempDta.totalLen-BUFFER_SIZE);  
  534.                     m_tempDta.totalLen-=BUFFER_SIZE;  
  535.                     goto lb2;//重新计算  
  536.                 }  
  537.                 break;  
  538.             }  
  539.         case 2:  
  540.             {  
  541.                 break;  
  542.             }  
  543.         case 3:  
  544.             {  
  545.                 TPack *pack=m_Receivepacks[ilen];  
  546.                 ULONG curlen=pack->CurPack-pack->data;  
  547.                 if (pack->totalLen==dat.totalLen-MinDataLen+curlen)//已经完成了数据包的接收  
  548.                 {  
  549.                     pack->AddData(dat.data+MinDataHeadLen,dat.totalLen-MinDataHeadLen);    
  550.                     m_pfRecvData(pack->data,pack->totalLen);  
  551.                     delete[] pack->data;  
  552.                     delete pack;  
  553.                     m_Receivepacks.erase(ilen);  
  554.                 }else if (pack->totalLen>len-MinDataLen+curlen)  
  555.                 {  
  556.                     if (dat.totalLen==BUFFER_SIZE)//不满一帧,继续等待  
  557.                     {  
  558.                         pack->AddData(dat.data+MinDataHeadLen,len-MinDataHeadLen);     
  559.                         m_tempDta.AddData(dat.data,dat.totalLen);  
  560.                     }else if(dat.totalLen>BUFFER_SIZE)                //满一帧,直接加入缓存  
  561.                     {  
  562.                         pack->AddData(dat.data+MinDataHeadLen,BUFFER_SIZE-MinDataHeadLen);     
  563.                         memcpy(m_tempDta.data,dat.data+BUFFER_SIZE,dat.totalLen-BUFFER_SIZE);  
  564.                         m_tempDta.totalLen-=BUFFER_SIZE;  
  565.                         goto lb2;  
  566.                     }  
  567.                 }else  
  568.                 {  
  569.                     pack->AddData(dat.data+MinDataHeadLen,pack->totalLen-curlen);   
  570.                     m_pfRecvData(pack->data,pack->totalLen);  
  571.                     ULONG tlen=MinDataHeadLen+pack->totalLen-curlen;  
  572.                     memcpy(m_tempDta.data,dat.data+tlen,dat.totalLen-tlen);  
  573.                     data+=tlen;  
  574.                     m_tempDta.totalLen-=tlen;  
  575.                     delete[] pack->data;  
  576.                     delete pack;  
  577.                     m_Receivepacks.erase(ilen);  
  578.                     goto lb2;//重新计算  
  579.                 }  
  580.                 break;  
  581.             }  
  582.         case 4:  
  583.             {  
  584.                 break;  
  585.             }  
  586.         default:  
  587.             {                     
  588.                 ULONG tlen=MinDataLen+ilen;  
  589.                 if (tlen==m_tempDta.totalLen)  
  590.                 {  
  591.                     m_pfRecvData(dat.Cur,ilen);  
  592.                     m_tempDta.clear();  
  593.                 }else if (tlen<m_tempDta.totalLen)  
  594.                 {  
  595.                     m_pfRecvData(dat.Cur,ilen);  
  596.                     memcpy(m_tempDta.data,dat.Cur+ilen,m_tempDta.totalLen-tlen);  
  597.                     m_tempDta.totalLen-=tlen;  
  598.                     goto lb2;//重新计算  
  599.                 }                     
  600.                 break;  
  601.             }  
  602.         }  
  603.     }                     
  604. }  
  605.   
  606. void TData::AddType(char type)  
  607. {  
  608.     totalLen=cSize;  
  609.     memcpy(data,&type,totalLen);          
  610. }  
  611. void TData::AddInt(ULONG len)  
  612. {                 
  613.     memcpy(data+totalLen,&len,ULSize);  
  614.     totalLen+=ULSize;  
  615. }  
  616. void TData::AddData(char *buf,ULONG len)  
  617. {  
  618.     int clen=len+totalLen>BUFFER_SIZE?BUFFER_SIZE-len:len;  
  619.     memcpy(data+totalLen,buf,clen);  
  620.     totalLen+=clen;  
  621. }  
  622.   
  623. char TData::GetType()  
  624. {  
  625.     char type;  
  626.     memcpy(&type,data,cSize);  
  627.     Cur=data+cSize;  
  628.     return type;  
  629. }  
  630. ULONG TData::GetInt()  
  631. {  
  632.     if (Cur-data+ULSize>totalLen)return 0;  
  633.     ULONG l;  
  634.     memcpy(&l,Cur,ULSize);  
  635.     Cur+=ULSize;  
  636.     return l;  
  637. }  
  638. char* TData::GetData(ULONG &retlen)  
  639. {  
  640.     retlen=totalLen-(ULONG)(Cur-data);        
  641.     return Cur;  
  642. }  
  643.   
  644.   
  645.   
  646.   
  647. </pre><br>  
  648. <br>  
  649. <pre></pre>  
  650. <p><br>  
  651. </p>  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值