声明:本文参考了langresser发布的blog“跨平台的游戏客户端Socket封装 ”
Socket处理是异步非阻塞的,所以可以放心的放到主线程处理消息,并且在原作者的基本上进行了系列优化,考虑了客户端可能建立多个SOCKET,因此加入了Manager概念,与cocos2d-x进行了融合。
本文基于cocos2d-x3.0+VS2012
文件目录结构截图:
文件源码:
TCPSocket.h
1 #ifndef __CC_TCPSOCKET_H__ 2 #define __CC_TCPSOCKET_H__ 3 4 #include "cocos2d.h" 5 #include "ExtensionMacros.h" 6 #include "WorldPacket.h" 7 #ifdef WIN32 8 #include <windows.h> 9 #include <WinSock.h> 10 #pragma comment( lib, "ws2_32.lib" ) 11 #else 12 #include <sys/socket.h> 13 #include <fcntl.h> 14 #include <errno.h> 15 #include <netinet/in.h> 16 #include <arpa/inet.h> 17 18 #define SOCKET int 19 #define SOCKET_ERROR -1 20 #define INVALID_SOCKET -1 21 22 #endif 23 24 NS_CC_EXT_BEGIN 25 #ifndef CHECKF 26 #define CHECKF(x) \ 27 do \ 28 { \ 29 if (!(x)) { \ 30 log_msg("CHECKF", #x, __FILE__, __LINE__); \ 31 return 0; \ 32 } \ 33 } while (0) 34 #endif 35 36 #define _MAX_MSGSIZE 16 * 1024 // 暂定一个消息最大为16k 37 #define BLOCKSECONDS 30 // INIT函数阻塞时间 38 #define INBUFSIZE (64*1024) //? 具体尺寸根据剖面报告调整 接收数据的缓存 39 #define OUTBUFSIZE (8*1024) //? 具体尺寸根据剖面报告调整。 发送数据的缓存,当不超过8K时,FLUSH只需要SEND一次 40 41 class CC_DLL TCPSocket 42 { 43 public: 44 TCPSocket(void); 45 bool Create(const char* pszServerIP, int nServerPort, int tagid, int nBlockSec = BLOCKSECONDS, bool bKeepAlive = false); 46 bool SendMsg(void* pBuf, int nSize); 47 bool ReceiveMsg(void* pBuf, int& nSize); 48 bool Flush(void); 49 bool Check(void); 50 void Destroy(void); 51 SOCKET GetSocket(void) const { return m_sockClient; } 52 53 int getTagID(){ return m_tag; } 54 private: 55 bool recvFromSock(void); // 从网络中读取尽可能多的数据 56 bool hasError(); // 是否发生错误,注意,异步模式未完成非错误 57 void closeSocket(); 58 59 SOCKET m_sockClient; 60 61 // 发送数据缓冲 62 char m_bufOutput[OUTBUFSIZE]; //? 可优化为指针数组 63 int m_nOutbufLen; 64 65 // 环形缓冲区 66 char m_bufInput[INBUFSIZE]; 67 int m_nInbufLen; 68 int m_nInbufStart; // INBUF使用循环式队列,该变量为队列起点,0 - (SIZE-1) 69 int m_tag; 70 }; 71 72 typedef std::function<bool(int,int,WorldPacket&)> ProAllFunc; // 接收所有协议,自行处理,@socket标识,@协议头,@数据包,返回是否分发 73 typedef std::function<void(int,WorldPacket&)> ProFunc; // 接收单个协议,@socket标识,@数据包 74 typedef std::function<void(int)> sckFunc; // 连接成功/断开事件 75 76 #define SCT_CALLBACK_1(func, _Object) std::bind(&func,_Object, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3) 77 #define SCT_CALLBACK_2(func, _Object) std::bind(&func,_Object, std::placeholders::_1, std::placeholders::_2) 78 #define SCT_CALLBACK_3(func, _Object) std::bind(&func,_Object, std::placeholders::_1) 79 // 创建SOCKET管理器 80 #define CREATE_TCPSOCKETMGR(pNode) pNode->addChild(new TCPSocketManager(), 0) 81 82 class CC_DLL TCPSocketManager : 83 public Node 84 { 85 public: 86 TCPSocketManager() 87 { 88 assert(!mSingleton); 89 this->mSingleton = this; 90 // 开启update 91 scheduleUpdate(); 92 }; 93 ~TCPSocketManager(){}; 94 // 创建socket并添加到管理器 95 TCPSocket *createSocket(const char* pszServerIP, // IP地址 96 int nServerPort, // 端口 97 int _tag, // 标识ID 98 int nBlockSec = BLOCKSECONDS, // 阻塞时间ms 99 bool bKeepAlive = false); 100 // 注册协议包 101 void register_process(const uint16 &entry, ProFunc callback); 102 // 注册接收所有协议 103 void register_all_process(ProAllFunc callback){ _pProcess = callback; } 104 // 注册socket连接成功事件 105 void register_connect(sckFunc callback){ _pOnConnect = callback; } 106 // 注册socket断线事件 107 void register_disconnect(sckFunc callback){ _OnDisconnect = callback; } 108 109 // 单独添加socket到管理器 110 bool addSocket(TCPSocket *pSocket); 111 // 删除socket 112 bool removeSocket(int _tag); 113 // 断开socket 114 void disconnect(int _tag); 115 // 获取socket 116 TCPSocket *GetSocket(int _tag); 117 // 发送消息 118 bool SendPacket(int _tag, WorldPacket *packet); 119 120 void update(float delta); 121 122 static TCPSocketManager &getSingleton(){ assert(mSingleton); return *mSingleton;} 123 124 private: 125 ProAllFunc _pProcess; 126 sckFunc _pOnConnect; 127 sckFunc _OnDisconnect; 128 std::list<TCPSocket*> m_lstSocket; 129 std::map<uint16, ProFunc> _mapProcess; 130 static TCPSocketManager * mSingleton; 131 }; 132 133 #define sSocketMgr TCPSocketManager::getSingleton() 134 NS_CC_EXT_END 135 136 #endif //__CC_TCPSOCKET_H__
TCPSocket.cpp
#include "TCPSocket.h" #include "support/zip_support/unzip.h" NS_CC_EXT_BEGIN TCPSocket::TCPSocket() { // 初始化 memset(m_bufOutput, 0, sizeof(m_bufOutput)); memset(m_bufInput, 0, sizeof(m_bufInput)); } void TCPSocket::closeSocket() { #ifdef WIN32 closesocket(m_sockClient); WSACleanup(); #else close(m_sockClient); #endif } bool TCPSocket::Create(const char* pszServerIP, int nServerPort, int tagid, int nBlockSec, bool bKeepAlive /*= FALSE*/) { // 检查参数 if(pszServerIP == 0 || strlen(pszServerIP) > 15) { return false; } #ifdef WIN32 WSADATA wsaData; WORD version = MAKEWORD(2, 0); int ret = WSAStartup(version, &wsaData);//win sock start up if (ret != 0) { return false; } #endif // 创建主套接字 m_sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(m_sockClient == INVALID_SOCKET) { closeSocket(); return false; } // 设置SOCKET为KEEPALIVE if(bKeepAlive) { int optval=1; if(setsockopt(m_sockClient, SOL_SOCKET, SO_KEEPALIVE, (char *) &optval, sizeof(optval))) { closeSocket(); return false; } } #ifdef WIN32 DWORD nMode = 1; int nRes = ioctlsocket(m_sockClient, FIONBIO, &nMode); if (nRes == SOCKET_ERROR) { closeSocket(); return false; } #else // 设置为非阻塞方式 fcntl(m_sockClient, F_SETFL, O_NONBLOCK); #endif unsigned long serveraddr = inet_addr(pszServerIP); if(serveraddr == INADDR_NONE) // 检查IP地址格式错误 { closeSocket(); return false; } sockaddr_in addr_in; memset((void *)&addr_in, 0, sizeof(addr_in)); addr_in.sin_family = AF_INET; addr_in.sin_port = htons(nServerPort); addr_in.sin_addr.s_addr = serveraddr; if(connect(m_sockClient, (sockaddr *)&addr_in, sizeof(addr_in)) == SOCKET_ERROR) { if (hasError()) { closeSocket(); return false; } else // WSAWOLDBLOCK { timeval timeout; timeout.tv_sec = nBlockSec; timeout.tv_usec = 0; fd_set writeset, exceptset; FD_ZERO(&writeset); FD_ZERO(&exceptset); FD_SET(m_sockClient, &writeset); FD_SET(m_sockClient, &exceptset); int ret = select(FD_SETSIZE, NULL, &writeset, &exceptset, &timeout); if (ret == 0 || ret < 0) { closeSocket(); return false; } else // ret > 0 { ret = FD_ISSET(m_sockClient, &exceptset); if(ret) // or (!FD_ISSET(m_sockClient, &writeset) { closeSocket(); return false; } } } } m_nInbufLen = 0; m_nInbufStart = 0; m_nOutbufLen = 0; struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 500; setsockopt(m_sockClient, SOL_SOCKET, SO_LINGER, (const char*)&so_linger, sizeof(so_linger)); m_tag = tagid; return true; } bool TCPSocket::SendMsg(void* pBuf, int nSize) { if(pBuf == 0 || nSize <= 0) { return false; } if (m_sockClient == INVALID_SOCKET) { return false; } // 检查通讯消息包长度 int packsize = 0; packsize = nSize; // 检测BUF溢出 if(m_nOutbufLen + nSize > OUTBUFSIZE) { // 立即发送OUTBUF中的数据,以清空OUTBUF。 Flush(); if(m_nOutbufLen + nSize > OUTBUFSIZE) { // 出错了 Destroy(); return false; } } // 数据添加到BUF尾 memcpy(m_bufOutput + m_nOutbufLen, pBuf, nSize); m_nOutbufLen += nSize; return true; } bool TCPSocket::ReceiveMsg(void* pBuf, int& nSize) { //检查参数 if(pBuf == NULL || nSize <= 0) { return false; } if (m_sockClient == INVALID_SOCKET) { return false; } // 检查是否有一个消息(小于2则无法获取到消息长度) if(m_nInbufLen < 2) { // 如果没有请求成功 或者 如果没有数据则直接返回 if(!recvFromSock() || m_nInbufLen < 2) { // 这个m_nInbufLen更新了 return false; } } // 计算要拷贝的消息的大小(一个消息,大小为整个消息的第一个16字节),因为环形缓冲区,所以要分开计算 int packsize = (unsigned char)m_bufInput[m_nInbufStart+2] + (unsigned char)m_bufInput[(m_nInbufStart + 3) % INBUFSIZE] * 256; // 注意字节序,高位+低位 // 检测消息包尺寸错误 暂定最大16k if (packsize <= 0 || packsize > _MAX_MSGSIZE) { m_nInbufLen = 0; // 直接清空INBUF m_nInbufStart = 0; return false; } // 检查消息是否完整(如果将要拷贝的消息大于此时缓冲区数据长度,需要再次请求接收剩余数据) if (packsize > m_nInbufLen) { // 如果没有请求成功 或者 依然无法获取到完整的数据包 则返回,直到取得完整包 if (!recvFromSock() || packsize > m_nInbufLen) { // 这个m_nInbufLen已更新 return false; } } // 复制出一个消息 if(m_nInbufStart + packsize > INBUFSIZE) { // 如果一个消息有回卷(被拆成两份在环形缓冲区的头尾) // 先拷贝环形缓冲区末尾的数据 int copylen = INBUFSIZE - m_nInbufStart; memcpy(pBuf, m_bufInput + m_nInbufStart, copylen); // 再拷贝环形缓冲区头部的剩余部分 memcpy((unsigned char *)pBuf + copylen, m_bufInput, packsize - copylen); nSize = packsize; } else { // 消息没有回卷,可以一次拷贝出去 memcpy(pBuf, m_bufInput + m_nInbufStart, packsize); nSize = packsize; } // 重新计算环形缓冲区头部位置 m_nInbufStart = (m_nInbufStart + packsize) % INBUFSIZE; m_nInbufLen -= packsize; return true; } bool TCPSocket::hasError() { #ifdef WIN32 int err = WSAGetLastError(); if(err != WSAEWOULDBLOCK) { #else int err = errno; if(err != EINPROGRESS && err != EAGAIN) { #endif return true; } return false; } // 从网络中读取尽可能多的数据,实际向服务器请求数据的地方 bool TCPSocket::recvFromSock(void) { if (m_nInbufLen >= INBUFSIZE || m_sockClient == INVALID_SOCKET) { return false; } // 接收第一段数据 int savelen, savepos; // 数据要保存的长度和位置 if(m_nInbufStart + m_nInbufLen < INBUFSIZE) { // INBUF中的剩余空间有回绕 savelen = INBUFSIZE - (m_nInbufStart + m_nInbufLen); // 后部空间长度,最大接收数据的长度 } else { savelen = INBUFSIZE - m_nInbufLen; } // 缓冲区数据的末尾 savepos = (m_nInbufStart + m_nInbufLen) % INBUFSIZE; //CHECKF(savepos + savelen <= INBUFSIZE); int inlen = recv(m_sockClient, m_bufInput + savepos, savelen, 0); if(inlen > 0) { // 有接收到数据 m_nInbufLen += inlen; if (m_nInbufLen > INBUFSIZE) { return false; } // 接收第二段数据(一次接收没有完成,接收第二段数据) if(inlen == savelen && m_nInbufLen < INBUFSIZE) { int savelen = INBUFSIZE - m_nInbufLen; int savepos = (m_nInbufStart + m_nInbufLen) % INBUFSIZE; //CHECKF(savepos + savelen <= INBUFSIZE); inlen = recv(m_sockClient, m_bufInput + savepos, savelen, 0); if(inlen > 0) { m_nInbufLen += inlen; if (m_nInbufLen > INBUFSIZE) { return false; } } else if(inlen == 0) { Destroy(); return false; } else { // 连接已断开或者错误(包括阻塞) if (hasError()) { Destroy(); return false; } } } } else if(inlen == 0) { Destroy(); return false; } else { // 连接已断开或者错误(包括阻塞) if (hasError()) { Destroy(); return false; } } return true; } bool TCPSocket::Flush(void) //? 如果 OUTBUF > SENDBUF 则需要多次SEND() { if (m_sockClient == INVALID_SOCKET) { return false; } if(m_nOutbufLen <= 0) { return true; } // 发送一段数据 int outsize; outsize = send(m_sockClient, m_bufOutput, m_nOutbufLen, 0); if(outsize > 0) { // 删除已发送的部分 if(m_nOutbufLen - outsize > 0) { memcpy(m_bufOutput, m_bufOutput + outsize, m_nOutbufLen - outsize); } m_nOutbufLen -= outsize; if (m_nOutbufLen < 0) { return false; } } else { if (hasError()) { Destroy(); return false; } } return true; } bool TCPSocket::Check(void) { // 检查状态 if (m_sockClient == INVALID_SOCKET) { return false; } char buf[1]; int ret = recv(m_sockClient, buf, 1, MSG_PEEK); if(ret == 0) { Destroy(); return false; } else if(ret < 0) { if (hasError()) { Destroy(); return false; } else { // 阻塞 return true; } } else { // 有数据 return true; } return true; } void TCPSocket::Destroy(void) { // 关闭 struct linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 500; int ret = setsockopt(m_sockClient, SOL_SOCKET, SO_LINGER, (const char*)&so_linger, sizeof(so_linger)); closeSocket(); m_sockClient = INVALID_SOCKET; m_nInbufLen = 0; m_nInbufStart = 0; m_nOutbufLen = 0; memset(m_bufOutput, 0, sizeof(m_bufOutput)); memset(m_bufInput, 0, sizeof(m_bufInput)); } TCPSocketManager *TCPSocketManager::mSingleton = 0; TCPSocket *TCPSocketManager::createSocket(const char* pszServerIP, // IP地址 int nServerPort, // 端口 int _tag, // 标识ID int nBlockSec, // 阻塞时间ms bool bKeepAlive) { TCPSocket *pSocket = new TCPSocket(); if (pSocket->Create(pszServerIP, nServerPort, _tag, nBlockSec, bKeepAlive)) { assert(addSocket(pSocket)); if (_pOnConnect){ _pOnConnect(_tag); } return pSocket; } delete pSocket; return NULL; } bool TCPSocketManager::addSocket(TCPSocket *pSocket) { std::list<TCPSocket*>::iterator iter, enditer = m_lstSocket.end(); for (iter = m_lstSocket.begin(); iter != enditer; ++ iter) { if ((*iter)->GetSocket() == pSocket->GetSocket()) return false; } m_lstSocket.push_back(pSocket); return true; } // 删除socket bool TCPSocketManager::removeSocket(int _tag) { std::list<TCPSocket*>::iterator iter, enditer = m_lstSocket.end(); for (iter = m_lstSocket.begin(); iter != enditer; ++ iter) { if ((*iter)->getTagID() == _tag) { (*iter)->Destroy(); m_lstSocket.erase(iter); return true; } } return false; } TCPSocket *TCPSocketManager::GetSocket(int _tag) { std::list<TCPSocket*>::iterator iter, enditer = m_lstSocket.end(); for (iter = m_lstSocket.begin(); iter != enditer; ++ iter) { if ((*iter)->getTagID() == _tag) { return *iter; } } return NULL; } void TCPSocketManager::update(float delta) { std::list<TCPSocket*>::iterator iter, enditer = m_lstSocket.end(); for (iter = m_lstSocket.begin(); iter != enditer; ++ iter) { TCPSocket *pSocket = *iter; int _tag = pSocket->getTagID(); if (!pSocket->Check()) {// 掉线了 _OnDisconnect(_tag); m_lstSocket.erase(iter); break; } while (true) { char buffer[_MAX_MSGSIZE] = {0}; int nSize = sizeof(buffer); char *pbufMsg = buffer; if (!pSocket->ReceiveMsg(pbufMsg, nSize)) break; WorldPacket packet; uint16 _cmd, _length; packet.Write((uint8*)pbufMsg, nSize); packet >> _cmd >> _length; if (_cmd & 0x8000) { Byte uncompr[1024] = {0}; uLong uncomprLen; _cmd &= 0x7fff; uncompress(uncompr, &uncomprLen, packet.contents()+4, packet.size()-4); } if (_pProcess == 0 || _pProcess(pSocket->getTagID(), _cmd, packet)) {// 分发数据 std::map<uint16, ProFunc>::iterator mapi = _mapProcess.find(_cmd); if (mapi == _mapProcess.end()) continue; mapi->second(pSocket->getTagID(), packet); } } } } void TCPSocketManager::register_process(const uint16 &entry, ProFunc callback) { _mapProcess[entry] = callback; } bool TCPSocketManager::SendPacket(int _tag, WorldPacket *packet) { std::list<TCPSocket*>::iterator iter, enditer = m_lstSocket.end(); for (iter = m_lstSocket.begin(); iter != enditer; ++ iter) { if ((*iter)->getTagID() == _tag) { (*iter)->SendMsg((void *)packet->contents(), packet->size()); return (*iter)->Flush(); } } return false; } void TCPSocketManager::disconnect(int _tag) { std::list<TCPSocket*>::iterator iter, enditer = m_lstSocket.end(); for (iter = m_lstSocket.begin(); iter != enditer; ++ iter) { if ((*iter)->getTagID() == _tag) { (*iter)->Destroy(); if (_OnDisconnect){ _OnDisconnect(_tag); } break; } } } NS_CC_EXT_END
ByteBuffer.h (读写数据包)
1 /**************************************************************************** 2 * 3 * ByteBuffer Class 4 * 5 */ 6 7 #ifndef _BYTEBUFFER_H 8 #define _BYTEBUFFER_H 9 10 #include "Common.h" 11 //#include "Vector3.h" 12 13 class ByteBuffer 14 { 15 #define DEFAULT_SIZE 0x1000 16 #define DEFAULT_INCREASE_SIZE 200 17 uint8 * m_buffer; 18 size_t m_readPos; 19 size_t m_writePos; 20 uint32 m_buffersize; 21 22 public: 23 /** Creates a bytebuffer with the default size 24 */ 25 ByteBuffer() 26 { 27 m_buffer =0; 28 m_readPos = m_writePos = 0; 29 m_buffersize = 0; 30 reserve(DEFAULT_SIZE); 31 } 32 33 /** Creates a bytebuffer with the specified size 34 */ 35 ByteBuffer(size_t res) 36 { 37 m_buffer =0; 38 m_readPos = m_writePos = 0; 39 m_buffersize = 0; 40 reserve(res); 41 } 42 43 /** Frees the allocated buffer 44 */ 45 ~ByteBuffer() 46 { 47 free(m_buffer); 48 } 49 50 51 /** Allocates/reallocates buffer with specified size. 52 */ 53 void reserve(size_t res) 54 { 55 if(m_buffer) 56 m_buffer = (uint8*)realloc(m_buffer, res); 57 else 58 m_buffer = (uint8*)malloc(res); 59 60 m_buffersize = res; 61 } 62 63 64 /** Resets read/write indexes 65 */ 66 inline void clear() 67 { 68 m_readPos = m_writePos = 0; 69 } 70 71 /** Sets write position 72 */ 73 inline void resize(size_t size) 74 { 75 m_writePos = size; 76 } 77 78 /** Returns the buffer pointer 79 */ 80 inline const uint8 * contents() 81 { 82 return m_buffer; 83 } 84 85 86 /** Gets the buffer size. 87 */ 88 uint32 GetBufferSize() { return m_writePos; } 89 90 /** Reads sizeof(T) bytes from the buffer 91 * @return the bytes read 92 */ 93 template<typename T> 94 T Read() 95 { 96 if(m_readPos + sizeof(T) > m_writePos) 97 return (T)0; 98 T ret = *(T*)&m_buffer[m_readPos]; 99 m_readPos += sizeof(T); 100 return ret; 101 } 102 103 void skip(size_t len) 104 { 105 if(m_readPos + len > m_writePos) 106 len = (m_writePos - m_readPos); 107 m_readPos += len; 108 } 109 110 /** Reads x bytes from the buffer 111 */ 112 void read(uint8 * buffer, size_t len) 113 { 114 if(m_readPos + len > m_writePos) 115 len = (m_writePos - m_readPos); 116 117 memcpy(buffer, &m_buffer[m_readPos], len); 118 m_readPos += len; 119 } 120 121 /** Writes sizeof(T) bytes to the buffer, while checking for overflows. 122 * @param T data The data to be written 123 */ 124 template<typename T> 125 void Write(const T & data) 126 { 127 size_t new_size = m_writePos + sizeof(T); 128 if(new_size > m_buffersize) 129 { 130 new_size = (new_size / DEFAULT_INCREASE_SIZE + 1) * DEFAULT_INCREASE_SIZE; 131 reserve(new_size); 132 } 133 134 *(T*)&m_buffer[m_writePos] = data; 135 m_writePos += sizeof(T); 136 } 137 138 /** writes x bytes to the buffer, while checking for overflows 139 * @param ptr the data to be written 140 * @param size byte count 141 */ 142 void Write(const uint8 * data, size_t size) 143 { 144 size_t new_size = m_writePos + size; 145 if(new_size > m_buffersize) 146 { 147 new_size = (new_size / DEFAULT_INCREASE_SIZE + 1) * DEFAULT_INCREASE_SIZE; 148 reserve(new_size); 149 } 150 151 memcpy(&m_buffer[m_writePos], data, size); 152 m_writePos += size; 153 } 154 155 /** Ensures the buffer is big enough to fit the specified number of bytes. 156 * @param bytes number of bytes to fit 157 */ 158 inline void EnsureBufferSize(uint32 Bytes) 159 { 160 size_t new_size = m_writePos + Bytes; 161 if(new_size > m_buffersize) 162 { 163 new_size = (new_size / DEFAULT_INCREASE_SIZE + 1) * DEFAULT_INCREASE_SIZE; 164 reserve(new_size); 165 } 166 167 } 168 169 /** These are the default read/write operators. 170 */ 171 #define DEFINE_BUFFER_READ_OPERATOR(type) void operator >> (type& dest) { dest = Read<type>(); } 172 #define DEFINE_BUFFER_WRITE_OPERATOR(type) void operator << (const type src) { Write<type>(src); } 173 174 /** Fast read/write operators without using the templated read/write functions. 175 */ 176 #define DEFINE_FAST_READ_OPERATOR(type, size) ByteBuffer& operator >> (type& dest) { if(m_readPos + size > m_writePos) { dest = (type)0; return *this; } else { dest = *(type*)&m_buffer[m_readPos]; m_readPos += size; return *this; } } 177 #define DEFINE_FAST_WRITE_OPERATOR(type, size) ByteBuffer& operator << (const type src) { if(m_writePos + size > m_buffersize) { reserve(m_buffersize + DEFAULT_INCREASE_SIZE); } *(type*)&m_buffer[m_writePos] = src; m_writePos += size; return *this; } 178 179 /** Integer/float r/w operators 180 */ 181 DEFINE_FAST_READ_OPERATOR(uint64, 8); 182 DEFINE_FAST_READ_OPERATOR(uint32, 4); 183 DEFINE_FAST_READ_OPERATOR(uint16, 2); 184 DEFINE_FAST_READ_OPERATOR(uint8, 1); 185 DEFINE_FAST_READ_OPERATOR(int64, 8); 186 DEFINE_FAST_READ_OPERATOR(int32, 4); 187 DEFINE_FAST_READ_OPERATOR(int16, 2); 188 DEFINE_FAST_READ_OPERATOR(int8, 1); 189 DEFINE_FAST_READ_OPERATOR(float, 4); 190 DEFINE_FAST_READ_OPERATOR(double, 8); 191 192 DEFINE_FAST_WRITE_OPERATOR(uint64, 8); 193 DEFINE_FAST_WRITE_OPERATOR(uint32, 4); 194 DEFINE_FAST_WRITE_OPERATOR(uint16, 2); 195 DEFINE_FAST_WRITE_OPERATOR(uint8, 1); 196 DEFINE_FAST_WRITE_OPERATOR(int64, 8); 197 DEFINE_FAST_WRITE_OPERATOR(int32, 4); 198 DEFINE_FAST_WRITE_OPERATOR(int16, 2); 199 DEFINE_FAST_WRITE_OPERATOR(int8, 1); 200 DEFINE_FAST_WRITE_OPERATOR(float, 4); 201 DEFINE_FAST_WRITE_OPERATOR(double, 8); 202 203 /** boolean (1-byte) read/write operators 204 */ 205 DEFINE_FAST_WRITE_OPERATOR(bool, 1); 206 ByteBuffer& operator >> (bool & dst) { dst = (Read<char>() > 0 ? true : false); return *this; } 207 208 /** string (null-terminated) operators 209 */ 210 ByteBuffer& operator << (const std::string & value) { EnsureBufferSize(value.length() + 1); memcpy(&m_buffer[m_writePos], value.c_str(), value.length()+1); m_writePos += (value.length() + 1); return *this; } 211 ByteBuffer& operator >> (std::string & dest) 212 { 213 dest.clear(); 214 char c; 215 for(;;) 216 { 217 c = Read<char>(); 218 if(c == 0) break; 219 dest += c; 220 } 221 return *this; 222 } 223 224 /** Gets the write position 225 * @return buffer size 226 */ 227 inline size_t size() { return m_writePos; } 228 229 /** read/write position setting/getting 230 */ 231 inline size_t rpos() { return m_readPos; } 232 inline size_t wpos() { return m_writePos; } 233 inline void rpos(size_t p) { assert(p <= m_writePos); m_readPos = p; } 234 inline void wpos(size_t p) { assert(p <= m_buffersize); m_writePos = p; } 235 236 template<typename T> size_t writeVector(std::vector<T> &v) 237 { 238 for (typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); i++) { 239 Write<T>(*i); 240 } 241 return v.size(); 242 243 } 244 template<typename T> size_t readVector(size_t vsize, std::vector<T> &v) 245 { 246 247 v.clear(); 248 while(vsize--) { 249 T t = Read<T>(); 250 v.push_back(t); 251 } 252 return v.size(); 253 } 254 255 template<typename T> size_t writeList(std::list<T> &v) 256 { 257 for (typename std::list<T>::const_iterator i = v.begin(); i != v.end(); i++) { 258 Write<T>(*i); 259 } 260 return v.size(); 261 262 } 263 template<typename T> size_t readList(size_t vsize, std::list<T> &v) 264 { 265 266 v.clear(); 267 while(vsize--) { 268 T t = Read<T>(); 269 v.push_back(t); 270 } 271 return v.size(); 272 } 273 274 template <typename K, typename V> size_t writeMap(const std::map<K, V> &m) 275 { 276 for (typename std::map<K, V>::const_iterator i = m.begin(); i != m.end(); i++) { 277 Write<K>(i->first); 278 Write<V>(i->second); 279 } 280 return m.size(); 281 } 282 283 template <typename K, typename V> size_t readMap(size_t msize, std::map<K, V> &m) 284 { 285 m.clear(); 286 while(msize--) { 287 K k = Read<K>(); 288 V v = Read<V>(); 289 m.insert(make_pair(k, v)); 290 } 291 return m.size(); 292 } 293 294 }; 295 296 /// 297 /// 298 /// 299 300 template <typename T> ByteBuffer &operator<<(ByteBuffer &b, const std::vector<T> & v) 301 { 302 b << (uint32)v.size(); 303 for (typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); i++) { 304 b << *i; 305 } 306 return b; 307 } 308 309 template <typename T> ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v) 310 { 311 uint32 vsize; 312 b >> vsize; 313 v.clear(); 314 while(vsize--) { 315 T t; 316 b >> t; 317 v.push_back(t); 318 } 319 return b; 320 } 321 322 template <typename T> ByteBuffer &operator<<(ByteBuffer &b, const std::list<T> & v) 323 { 324 b << (uint32)v.size(); 325 for (typename std::list<T>::const_iterator i = v.begin(); i != v.end(); i++) { 326 b << *i; 327 } 328 return b; 329 } 330 331 template <typename T> ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v) 332 { 333 uint32 vsize; 334 b >> vsize; 335 v.clear(); 336 while(vsize--) { 337 T t; 338 b >> t; 339 v.push_back(t); 340 } 341 return b; 342 } 343 344 template <typename K, typename V> ByteBuffer &operator<<(ByteBuffer &b, const std::map<K, V> &m) 345 { 346 b << (uint32)m.size(); 347 for (typename std::map<K, V>::const_iterator i = m.begin(); i != m.end(); i++) { 348 b << i->first << i->second; 349 } 350 return b; 351 } 352 353 template <typename K, typename V> ByteBuffer &operator>>(ByteBuffer &b, std::map<K, V> &m) 354 { 355 uint32 msize; 356 b >> msize; 357 m.clear(); 358 while(msize--) { 359 K k; 360 V v; 361 b >> k >> v; 362 m.insert(make_pair(k, v)); 363 } 364 return b; 365 } 366 367 #endif
WorldPacket.h (读写扩展类,协议前2字节表示协议包,其次2字节表示数据大小)
1 #ifndef WGSERVER_WORLDPACKET_H 2 #define WGSERVER_WORLDPACKET_H 3 4 5 #include "ByteBuffer.h" 6 7 8 class WorldPacket : public ByteBuffer 9 { 10 public: 11 __inline WorldPacket() : ByteBuffer(), m_opcode(0) { } 12 __inline WorldPacket(uint16 opcode, size_t res) : ByteBuffer(res), m_opcode(opcode) {} 13 __inline WorldPacket(size_t res) : ByteBuffer(res), m_opcode(0) { } 14 __inline WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) {} 15 16 //! Clear packet and set opcode all in one mighty blow 17 __inline void Initialize(uint16 opcode ) 18 { 19 clear(); 20 m_opcode = opcode; 21 } 22 23 __inline uint16 GetOpcode() const { return m_opcode; } 24 __inline void SetOpcode(const uint16 & opcode) { m_opcode = opcode; } 25 __inline void SetLength(const uint16 & len) { 26 uint16 * plen = (uint16 * ) &(contents()[2]); 27 *plen = len; 28 } 29 30 __inline std::string getString() 31 { 32 //std::string buff = 33 return (const char*)contents(); 34 } 35 36 template<typename T> 37 void SetOffset(const uint16 & offset, const T value ) { 38 T * pval = (T *) &(contents()[offset]); 39 *pval = value; 40 } 41 42 public: 43 /** 44 * @创建时间 2011-08-31 45 * @创建人 李志勇 46 * @函数作用 向数据包追加字符串 47 * @参数 48 * @packet 数据封包指针 49 * @str 追加的字符串 50 */ 51 template<typename T> void AppendPacketString(std::string str) 52 { 53 T ilen = (T)str.size(); 54 *this << ilen; 55 if (ilen > 0) 56 Write((const uint8 *) str.c_str(), ilen); 57 } 58 /** 59 * @创建时间 2011-08-31 60 * @创建人 李志勇 61 * @函数作用 获取字符串 62 * @参数 63 * @packet 数据封包 64 * @返回 是否成功 65 */ 66 template<typename T> bool GetPacketString(std::string &str) 67 { 68 T ilen; 69 *this >> ilen; 70 if (ilen == 0) 71 return true; 72 uint8 buf[ilen+1]; 73 uint16 plen = size(); 74 if (plen < ilen) 75 return false; 76 read(buf, ilen); 77 buf[ilen] = 0; 78 str = (char*)buf; 79 return true; 80 } 81 82 83 protected: 84 uint16 m_opcode; 85 }; 86 87 /* 88 template<uint32 Size> 89 class SERVER_DECL StackWorldPacket : public StackBuffer<Size> 90 { 91 uint16 m_opcode; 92 public: 93 __inline StackWorldPacket(uint16 opcode) : StackBuffer<Size>(), m_opcode(opcode) { } 94 95 //! Clear packet and set opcode all in one mighty blow 96 __inline void Initialize(uint16 opcode ) 97 { 98 StackBuffer<Size>::Clear(); 99 m_opcode = opcode; 100 } 101 102 uint16 GetOpcode() { return m_opcode; } 103 __inline void SetOpcode(uint16 opcode) { m_opcode = opcode; } 104 }; 105 */ 106 107 #endif
Common.h (bytebuffer.h所需的一些定义,该文件来自“魔兽世界服务端”源码,cocos2d-x自身有个CCommon.h文件,如果把两个文件合并的话,在linux下编译会发生冲突,冲突较多,本人也没有做区分,因此建议独立出来)
1 #ifndef WGSERVER_COMMON_H 2 #define WGSERVER_COMMON_H 3 4 5 #ifdef WIN32 6 #pragma warning(disable:4996) 7 #define _CRT_SECURE_NO_DEPRECATE 1 8 #define _CRT_SECURE_COPP_OVERLOAD_STANDARD_NAMES 1 9 #pragma warning(disable:4251) // dll-interface bullshit 10 #endif 11 12 enum TimeVariables 13 { 14 TIME_SECOND = 1, 15 TIME_MINUTE = TIME_SECOND * 60, 16 TIME_HOUR = TIME_MINUTE * 60, 17 TIME_DAY = TIME_HOUR * 24, 18 TIME_MONTH = TIME_DAY * 30, 19 TIME_YEAR = TIME_MONTH * 12 20 }; 21 22 enum MsTimeVariables 23 { 24 MSTIME_SECOND = 1000, 25 MSTIME_MINUTE = MSTIME_SECOND * 60, 26 MSTIME_HOUR = MSTIME_MINUTE * 60, 27 MSTIME_DAY = MSTIME_HOUR * 24 28 }; 29 30 #ifdef WIN32 31 #define WGSERVER_INLINE __forceinline 32 #else 33 #define WGSERVER_INLINE inline 34 #endif 35 36 #ifdef HAVE_CONFIG_H 37 # include <config.h> 38 #endif 39 40 41 /* Define this if you're using a big-endian machine */ 42 #ifdef USING_BIG_ENDIAN 43 #include <machine/byte_order.h> 44 #define bswap_16(x) NXSwapShort(x) 45 #define bswap_32(x) NXSwapInt(x) 46 #define bswap_64(x) NXSwapLongLong(x) 47 #endif 48 49 #include <cstdlib> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <stdarg.h> 53 #include <time.h> 54 #include <math.h> 55 #include <errno.h> 56 //#include <sys/syscall.h> 57 58 59 #if defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 ) 60 # define WIN32_LEAN_AND_MEAN 61 //# define _WIN32_WINNT 0x0500 62 # define NOMINMAX 63 # include <windows.h> 64 #else 65 # include <string.h> 66 # define MAX_PATH 1024 67 #endif 68 69 #ifdef min 70 #undef min 71 #endif 72 73 #ifdef max 74 #undef max 75 #endif 76 77 #ifdef CONFIG_USE_SELECT 78 #undef FD_SETSIZE 79 #define FD_SETSIZE 2048 80 #endif 81 82 #if defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 ) 83 #include <winsock2.h> 84 #include <ws2tcpip.h> 85 #else 86 #include <sys/time.h> 87 #include <sys/types.h> 88 #include <sys/ioctl.h> 89 #include <sys/socket.h> 90 #include <netinet/in.h> 91 #include <arpa/inet.h> 92 #include <unistd.h> 93 #include <signal.h> 94 #include <netdb.h> 95 #endif 96 97 // current platform and compiler 98 #define PLATFORM_WIN32 0 99 #define PLATFORM_UNIX 1 100 #define PLATFORM_APPLE 2 101 102 #define UNIX_FLAVOUR_LINUX 1 103 #define UNIX_FLAVOUR_BSD 2 104 #define UNIX_FLAVOUR_OTHER 3 105 #define UNIX_FLAVOUR_OSX 4 106 107 #if defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 ) 108 # define PLATFORM PLATFORM_WIN32 109 #elif defined( __APPLE_CC__ ) 110 # define PLATFORM PLATFORM_APPLE 111 #else 112 # define PLATFORM PLATFORM_UNIX 113 #endif 114 115 #define COMPILER_MICROSOFT 0 116 #define COMPILER_GNU 1 117 #define COMPILER_BORLAND 2 118 119 #ifdef _MSC_VER 120 # define COMPILER COMPILER_MICROSOFT 121 #elif defined( __BORLANDC__ ) 122 # define COMPILER COMPILER_BORLAND 123 #elif defined( __GNUC__ ) 124 # define COMPILER COMPILER_GNU 125 #else 126 # pragma error "FATAL ERROR: Unknown compiler." 127 #endif 128 129 #if PLATFORM == PLATFORM_UNIX || PLATFORM == PLATFORM_APPLE 130 #ifdef HAVE_DARWIN 131 #define PLATFORM_TEXT "MacOSX" 132 #define UNIX_FLAVOUR UNIX_FLAVOUR_OSX 133 #else 134 #ifdef USE_KQUEUE 135 #define PLATFORM_TEXT "FreeBSD" 136 #define UNIX_FLAVOUR UNIX_FLAVOUR_BSD 137 #else 138 #define PLATFORM_TEXT "Linux" 139 #define UNIX_FLAVOUR UNIX_FLAVOUR_LINUX 140 #endif 141 #endif 142 #endif 143 144 #if PLATFORM == PLATFORM_WIN32 145 #define PLATFORM_TEXT "Win32" 146 #endif 147 148 #ifdef _DEBUG 149 #define CONFIG "Debug" 150 #else 151 #define CONFIG "Release" 152 #endif 153 154 #ifdef USING_BIG_ENDIAN 155 #define ARCH "PPC" 156 #else 157 #ifdef X64 158 #define ARCH "X64" 159 #else 160 #define ARCH "X86" 161 #endif 162 #endif 163 164 /*#if COMPILER == COMPILER_MICROSOFT 165 # pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data 166 # pragma warning( disable : 4311 ) // 'type cast': pointer truncation from HMODULE to uint32 167 # pragma warning( disable : 4786 ) // identifier was truncated to '255' characters in the debug information 168 # pragma warning( disable : 4146 ) 169 # pragma warning( disable : 4800 ) 170 #endif*/ 171 172 #if PLATFORM == PLATFORM_WIN32 173 #define STRCASECMP stricmp 174 #else 175 #define STRCASECMP strcasecmp 176 #endif 177 178 #if PLATFORM == PLATFORM_WIN32 179 #define ASYNC_NET 180 #endif 181 182 #ifdef USE_EPOLL 183 #define CONFIG_USE_EPOLL 184 #endif 185 #ifdef USE_KQUEUE 186 #define CONFIG_USE_KQUEUE 187 #endif 188 #ifdef USE_SELECT 189 #define CONFIG_USE_SELECT 190 #endif 191 #ifdef USE_POLL 192 #define CONFIG_USE_POLL 193 #endif 194 195 #ifdef min 196 #undef min 197 #endif 198 199 #ifdef max 200 #undef max 201 #endif 202 203 #include <cstdlib> 204 #include <set> 205 #include <list> 206 #include <string> 207 #include <map> 208 #include <queue> 209 #include <sstream> 210 #include <algorithm> 211 #include <cstring> 212 #include <climits> 213 #include <cstdlib> 214 //#include <iostream> 215 216 #if defined ( __GNUC__ ) 217 # define LIKELY( _x ) \ 218 __builtin_expect( ( _x ), 1 ) 219 # define UNLIKELY( _x ) \ 220 __builtin_expect( ( _x ), 0 ) 221 #else 222 # define LIKELY( _x ) \ 223 _x 224 # define UNLIKELY( _x ) \ 225 _x 226 #endif 227 228 #if defined (__GNUC__) 229 # define GCC_VERSION (__GNUC__ * 10000 \ 230 + __GNUC_MINOR__ * 100 \ 231 + __GNUC_PATCHLEVEL__) 232 #endif 233 234 235 #ifndef WIN32 236 #ifndef X64 237 # if defined (__GNUC__) 238 # if GCC_VERSION >= 30400 239 # ifdef HAVE_DARWIN 240 # define __fastcall 241 # else 242 # define __fastcall __attribute__((__fastcall__)) 243 # endif 244 # else 245 # define __fastcall __attribute__((__regparm__(3))) 246 # endif 247 # else 248 # define __fastcall __attribute__((__fastcall__)) 249 # endif 250 #else 251 #define __fastcall 252 #endif 253 #endif 254 255 #ifdef HAVE_STDCXX_0X 256 #include <unordered_map> 257 #include <unordered_set> 258 #elif COMPILER == COMPILER_GNU && __GNUC__ >= 3 259 #include <ext/hash_map> 260 #include <ext/hash_set> 261 #else 262 #include <hash_map> 263 #include <hash_set> 264 #endif 265 266 267 268 #ifdef _STLPORT_VERSION 269 #define HM_NAMESPACE std 270 using std::hash_map; 271 using std::hash_set; 272 #elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1300 273 #define HM_NAMESPACE stdext 274 using stdext::hash_map; 275 using stdext::hash_set; 276 #define ENABLE_SHITTY_STL_HACKS 1 277 278 /* 279 # if GNUC_COMP_VER >= 430 280 # define HashMap ::std::tr1::unordered_map 281 # define HashSet ::std::tr1::unordered_set 282 # else 283 # define HashMap ::__gnu_cxx::hash_map 284 # define HashSet ::__gnu_cxx::hash_set 285 # endif 286 */ 287 288 #define HashMap ::__gnu_cxx::hash_map 289 #define HashSet ::__gnu_cxx::hash_set 290 291 292 // hacky stuff for vc++ 293 #define snprintf _snprintf 294 #define vsnprintf _vsnprintf 295 //#define strlen lstrlen 296 297 #ifdef WIN32 298 //typedef char TCHAR; 299 #define __T(x) x 300 #endif 301 302 // cebernic added it 303 #define __utf8(x) _StringToUTF8(x) 304 #define __ansi(x) _StringToANSI(x) 305 #define __isutf8(x) _IsStringUTF8(x) 306 307 308 #elif COMPILER == COMPILER_INTEL 309 #define HM_NAMESPACE std 310 using std::hash_map; 311 using std::hash_set; 312 #elif defined(HAVE_STDCXX_0X) 313 #define HM_NAMESPACE std 314 #define hash_map unordered_map 315 #define hash_set unordered_set 316 using std::unordered_map; 317 using std::unordered_set; 318 #elif COMPILER == COMPILER_GNU && __GNUC__ >= 3 319 #define HM_NAMESPACE __gnu_cxx 320 using __gnu_cxx::hash_map; 321 using __gnu_cxx::hash_set; 322 323 namespace __gnu_cxx 324 { 325 template<> struct hash<unsigned long long> 326 { 327 size_t operator()(const unsigned long long &__x) const { return (size_t)__x; } 328 }; 329 template<typename T> struct hash<T *> 330 { 331 size_t operator()(T * const &__x) const { return (size_t)__x; } 332 }; 333 334 }; 335 336 #else 337 #define HM_NAMESPACE std 338 using std::hash_map; 339 #endif 340 341 /* Use correct types for x64 platforms, too */ 342 #if COMPILER != COMPILER_GNU 343 typedef signed __int64 int64; 344 typedef signed __int32 int32; 345 typedef signed __int16 int16; 346 typedef signed __int8 int8; 347 348 typedef unsigned __int64 uint64; 349 typedef unsigned __int32 uint32; 350 typedef unsigned __int16 uint16; 351 typedef unsigned __int8 uint8; 352 typedef float Real; 353 #else 354 355 typedef int64_t int64; 356 typedef int32_t int32; 357 typedef int16_t int16; 358 typedef int8_t int8; 359 typedef uint64_t uint64; 360 typedef uint32_t uint32; 361 typedef uint16_t uint16; 362 typedef uint8_t uint8; 363 typedef uint32_t DWORD; 364 typedef float Real; 365 366 #endif 367 368 /* these can be optimized into assembly */ 369 #ifdef USING_BIG_ENDIAN 370 371 WGSERVER_INLINE static void swap16(uint16* p) { *p = bswap_16((uint16_t)*p); } 372 WGSERVER_INLINE static void swap32(uint32* p) { *p = bswap_32((uint32_t)*p); } 373 WGSERVER_INLINE static void swap64(uint64* p) { *p = bswap_64((uint64_t)*p);; } 374 375 WGSERVER_INLINE static float swapfloat(float p) 376 { 377 union { float asfloat; uint8 asbytes[4]; } u1, u2; 378 u1.asfloat = p; 379 /* swap! */ 380 u2.asbytes[0] = u1.asbytes[3]; 381 u2.asbytes[1] = u1.asbytes[2]; 382 u2.asbytes[2] = u1.asbytes[1]; 383 u2.asbytes[3] = u1.asbytes[0]; 384 385 return u2.asfloat; 386 } 387 388 WGSERVER_INLINE static double swapdouble(double p) 389 { 390 union { double asfloat; uint8 asbytes[8]; } u1, u2; 391 u1.asfloat = p; 392 /* swap! */ 393 u2.asbytes[0] = u1.asbytes[7]; 394 u2.asbytes[1] = u1.asbytes[6]; 395 u2.asbytes[2] = u1.asbytes[5]; 396 u2.asbytes[3] = u1.asbytes[4]; 397 u2.asbytes[4] = u1.asbytes[3]; 398 u2.asbytes[5] = u1.asbytes[2]; 399 u2.asbytes[6] = u1.asbytes[1]; 400 u2.asbytes[7] = u1.asbytes[0]; 401 402 return u2.asfloat; 403 } 404 405 WGSERVER_INLINE static void swapfloat(float * p) 406 { 407 union { float asfloat; uint8 asbytes[4]; } u1, u2; 408 u1.asfloat = *p; 409 /* swap! */ 410 u2.asbytes[0] = u1.asbytes[3]; 411 u2.asbytes[1] = u1.asbytes[2]; 412 u2.asbytes[2] = u1.asbytes[1]; 413 u2.asbytes[3] = u1.asbytes[0]; 414 *p = u2.asfloat; 415 } 416 417 WGSERVER_INLINE static void swapdouble(double * p) 418 { 419 union { double asfloat; uint8 asbytes[8]; } u1, u2; 420 u1.asfloat = *p; 421 /* swap! */ 422 u2.asbytes[0] = u1.asbytes[7]; 423 u2.asbytes[1] = u1.asbytes[6]; 424 u2.asbytes[2] = u1.asbytes[5]; 425 u2.asbytes[3] = u1.asbytes[4]; 426 u2.asbytes[4] = u1.asbytes[3]; 427 u2.asbytes[5] = u1.asbytes[2]; 428 u2.asbytes[6] = u1.asbytes[1]; 429 u2.asbytes[7] = u1.asbytes[0]; 430 *p = u2.asfloat; 431 } 432 433 WGSERVER_INLINE static uint16 swap16(uint16 p) { return bswap_16((uint16_t)p); } 434 WGSERVER_INLINE static uint32 swap32(uint32 p) { return bswap_32((uint32_t)p); } 435 WGSERVER_INLINE static uint64 swap64(uint64 p) { return bswap_64((uint64_t)p); } 436 437 WGSERVER_INLINE static void swap16(int16* p) { *p = bswap_16((uint16_t)*p); } 438 WGSERVER_INLINE static void swap32(int32* p) { *p = bswap_32((uint32_t)*p); } 439 WGSERVER_INLINE static void swap64(int64* p) { *p = bswap_64((uint64_t)*p); } 440 441 WGSERVER_INLINE static int16 swap16(int16 p) { return bswap_16((uint16_t)p); } 442 WGSERVER_INLINE static int32 swap32(int32 p) { return bswap_32((uint32_t)p); } 443 WGSERVER_INLINE static int64 swap64(int64 p) { return bswap_64((uint64_t)p); } 444 445 #endif 446 /* 447 Scripting system exports/imports 448 */ 449 450 #ifdef WIN32 451 #ifndef SCRIPTLIB 452 #define SERVER_DECL __declspec(dllexport) 453 #define SCRIPT_DECL __declspec(dllimport) 454 #else 455 #define SERVER_DECL __declspec(dllimport) 456 #define SCRIPT_DECL __declspec(dllexport) 457 #endif 458 #else 459 #define SERVER_DECL 460 #define SCRIPT_DECL 461 #endif 462 463 // Include all threading files 464 #include <assert.h> 465 //#include "Threading/Threading.h" 466 467 //#include "MersenneTwister.h" 468 469 #if COMPILER == COMPILER_MICROSOFT 470 471 #define I64FMT "%016I64X" 472 #define I64FMTD "%I64u" 473 #define SI64FMTD "%I64d" 474 #define snprintf _snprintf 475 #define atoll __atoi64 476 477 #else 478 479 #define stricmp strcasecmp 480 #define strnicmp strncasecmp 481 #define I64FMT "%016llX" 482 #define I64FMTD "%llu" 483 #define SI64FMTD "%lld" 484 485 #endif 486 487 #ifndef WIN32 488 #ifdef USING_BIG_ENDIAN 489 //#define GUID_HIPART(x) (*((uint32*)&(x))) 490 //#define GUID_LOPART(x) (*(((uint32*)&(x))+1)) 491 #define GUID_LOPART(x) ( ( x >> 32 ) ) 492 #define GUID_HIPART(x) ( ( x & 0x00000000ffffffff ) ) 493 #else 494 #define GUID_HIPART(x) ( ( x >> 32 ) ) 495 #define GUID_LOPART(x) ( ( x & 0x00000000ffffffff ) ) 496 #endif 497 #else 498 #define GUID_HIPART(x) (*(((uint32*)&(x))+1)) 499 #define GUID_LOPART(x) (*((uint32*)&(x))) 500 #endif 501 502 #define atol(a) strtoul( a, NULL, 10) 503 504 #define STRINGIZE(a) #a 505 506 // fix buggy MSVC's for variable scoping to be reliable =S 507 #define for if(true) for 508 509 #if COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1400 510 #pragma float_control(push) 511 #pragma float_control(precise, on) 512 #endif 513 514 // fast int abs 515 static inline int int32abs( const int value ) 516 { 517 return (value ^ (value >> 31)) - (value >> 31); 518 } 519 520 // fast int abs and recast to unsigned 521 static inline uint32 int32abs2uint32( const int value ) 522 { 523 return (uint32)(value ^ (value >> 31)) - (value >> 31); 524 } 525 526 /// Fastest Method of float2int32 527 static inline int float2int32(const float value) 528 { 529 #if !defined(X64) && COMPILER == COMPILER_MICROSOFT && !defined(USING_BIG_ENDIAN) 530 int i; 531 __asm { 532 fld value 533 frndint 534 fistp i 535 } 536 return i; 537 #else 538 union { int asInt[2]; double asDouble; } n; 539 n.asDouble = value + 6755399441055744.0; 540 541 #if USING_BIG_ENDIAN 542 return n.asInt [1]; 543 #else 544 return n.asInt [0]; 545 #endif 546 #endif 547 } 548 549 /// Fastest Method of long2int32 550 static inline int long2int32(const double value) 551 { 552 #if !defined(X64) && COMPILER == COMPILER_MICROSOFT && !defined(USING_BIG_ENDIAN) 553 int i; 554 __asm { 555 fld value 556 frndint 557 fistp i 558 } 559 return i; 560 #else 561 union { int asInt[2]; double asDouble; } n; 562 n.asDouble = value + 6755399441055744.0; 563 564 #if USING_BIG_ENDIAN 565 return n.asInt [1]; 566 #else 567 return n.asInt [0]; 568 #endif 569 #endif 570 } 571 572 #if COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1400 573 #pragma float_control(pop) 574 #endif 575 576 #ifndef WIN32 577 #include <sys/timeb.h> 578 #endif 579 580 581 extern uint32 system_start_time_t; 582 583 WGSERVER_INLINE uint32 now() 584 { 585 #ifdef WIN32 586 return GetTickCount(); 587 #else 588 struct timeval tv; 589 gettimeofday(&tv, NULL); 590 return ((tv.tv_sec - system_start_time_t) * 1000) + (tv.tv_usec / 1000); 591 #endif 592 } 593 594 #ifndef WIN32 595 #define FALSE 0 596 #define TRUE 1 597 #endif 598 599 #ifndef WIN32 600 #define Sleep(ms) usleep(1000*ms) 601 #endif 602 603 /*#ifdef WIN32 604 #ifndef __SHOW_STUPID_WARNINGS__ 605 #pragma warning(disable:4018) 606 #pragma warning(disable:4244) 607 #pragma warning(disable:4305) 608 #pragma warning(disable:4748) 609 #pragma warning(disable:4800) 610 #pragma warning(disable:4996) 611 #pragma warning(disable:4251) 612 #endif 613 #endif 614 615 #undef INTEL_COMPILER 616 #ifdef INTEL_COMPILER 617 #pragma warning(disable:279) 618 #pragma warning(disable:1744) 619 #pragma warning(disable:1740) 620 #endif*/ 621 622 //#include "Util.h" 623 struct WayPoint 624 { 625 WayPoint() 626 { 627 o = 0.0f; 628 } 629 uint32 id; 630 float x; 631 float y; 632 float z; 633 float o; 634 uint32 waittime; //ms 635 uint32 flags; 636 bool forwardemoteoneshot; 637 uint32 forwardemoteid; 638 bool backwardemoteoneshot; 639 uint32 backwardemoteid; 640 uint32 forwardskinid; 641 uint32 backwardskinid; 642 643 }; 644 645 struct spawn_timed_emotes 646 { 647 uint8 type; //1 standstate, 2 emotestate, 3 emoteoneshot 648 uint32 value; //get yar list elsewhere 649 char *msg; //maybe we wish to say smething while changing emote state 650 uint8 msg_type; //yell ? say ? 651 uint8 msg_lang; //yell ? say ? 652 uint32 expire_after; //going to nex faze in 653 }; 654 typedef std::list<spawn_timed_emotes*> TimedEmoteList; 655 656 WGSERVER_INLINE void reverse_array(uint8 * pointer, size_t count) 657 { 658 size_t x; 659 uint8 * temp = (uint8*)malloc(count); 660 memcpy(temp, pointer, count); 661 for(x = 0; x < count; ++x) 662 pointer[x] = temp[count-x-1]; 663 free(temp); 664 } 665 666 typedef std::vector<WayPoint*> WayPointMap; 667 668 int32 GetTimePeriodFromString(const char * str); 669 std::string ConvertTimeStampToString(uint32 timestamp); 670 std::string ConvertTimeStampToDataTime(uint32 timestamp); 671 672 uint32 DecimalToMask(uint32 dec); 673 674 WGSERVER_INLINE void wgs_TOLOWER(std::string& str) 675 { 676 for(size_t i = 0; i < str.length(); ++i) 677 str[i] = (char)tolower(str[i]); 678 } 679 680 WGSERVER_INLINE void wgs_TOUPPER(std::string& str) 681 { 682 for(size_t i = 0; i < str.length(); ++i) 683 str[i] = (char)toupper(str[i]); 684 } 685 686 // returns true if the ip hits the mask, otherwise false 687 inline static bool ParseCIDRBan(unsigned int IP, unsigned int Mask, unsigned int MaskBits) 688 { 689 // CIDR bans are a compacted form of IP / Submask 690 // So 192.168.1.0/255.255.255.0 would be 192.168.1.0/24 691 // IP's in the 192.168l.1.x range would be hit, others not. 692 unsigned char * source_ip = (unsigned char*)&IP; 693 unsigned char * mask = (unsigned char*)&Mask; 694 int full_bytes = MaskBits / 8; 695 int leftover_bits = MaskBits % 8; 696 //int byte; 697 698 // sanity checks for the data first 699 if( MaskBits > 32 ) 700 return false; 701 702 // this is the table for comparing leftover bits 703 static const unsigned char leftover_bits_compare[9] = { 704 0x00, // 00000000 705 0x80, // 10000000 706 0xC0, // 11000000 707 0xE0, // 11100000 708 0xF0, // 11110000 709 0xF8, // 11111000 710 0xFC, // 11111100 711 0xFE, // 11111110 712 0xFF, // 11111111 - This one isn't used 713 }; 714 715 // if we have any full bytes, compare them with memcpy 716 if( full_bytes > 0 ) 717 { 718 if( memcmp( source_ip, mask, full_bytes ) != 0 ) 719 return false; 720 } 721 722 // compare the left over bits 723 if( leftover_bits > 0 ) 724 { 725 if( ( source_ip[full_bytes] & leftover_bits_compare[leftover_bits] ) != 726 ( mask[full_bytes] & leftover_bits_compare[leftover_bits] ) ) 727 { 728 // one of the bits does not match 729 return false; 730 } 731 } 732 733 // all of the bits match that were testable 734 return true; 735 } 736 737 inline static unsigned int MakeIP(const char * str) 738 { 739 unsigned int bytes[4]; 740 unsigned int res; 741 if( sscanf(str, "%u.%u.%u.%u", &bytes[0], &bytes[1], &bytes[2], &bytes[3]) != 4 ) 742 return 0; 743 744 res = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24); 745 return res; 746 } 747 748 749 inline static unsigned int GetANetwork(unsigned int ip) 750 { 751 return (ip & 0x000000FF); 752 } 753 754 inline static unsigned int GetBNetwork(unsigned int ip) 755 { 756 return (ip & 0x0000FFFF); 757 } 758 759 inline static unsigned int GetCNetwork(unsigned int ip) 760 { 761 return (ip & 0x00FFFFFF); 762 } 763 764 765 //get current thread id 766 #define getThreadId() syscall(__NR_gettid) 767 768 // warning, by enabling this define you are aware that you are only delaying the inevitable 769 // some crashes are not recorable and those will stack up in time and lead to a full crash 770 // enabling this define will make windows servers shut down only the map instance in where the crash ocured 771 // during this forced shutdown players are not saved to avoid saving corrupted data 772 // there might be a lot of cases where each saved crash will lead to memory leaks or unhandled cases 773 // crashreports are still created and do use them to report the actaul problem that casued the crash 774 // fixing the problem that causes the crash is the proper way to fix things 775 //#define FORCED_SERVER_KEEPALIVE 776 777 778 #endif
另外,
在extensions/cocos-ext.h文件内加入
#include "network/TCPSocket.h"
在extensions/Android.mk文件内加入,使其在linux下能够编译到
network/TCPSocket.cpp \
使用例子,代码片段:
/// // 创建SOCKET管理器 CREATE_TCPSOCKETMGR(this); // 创建并添加SOCKET,参数:服务器IP,端口,自定义的SOCKET_ID标识 sSocketMgr.createSocket("192.168.0.183", 7502, 1); // 注册协议,参数:包头,回调函数 sSocketMgr.register_process(0x10, SCT_CALLBACK_2(HelloWorld::login, this)); // 注册消息截获事件,注册此事件后可以截获收到的所有消息,若回调函数返回true则本次事件会继续分发注册过的协议,返回false则不分发 sSocketMgr.register_all_process(SCT_CALLBACK_1(HelloWorld::process, this)); // 定义协议包 WorldPacket packet; packet.clear(); // 设置协议头 packet.SetOpcode(0x0010); packet << uint16(0x0010) << uint16(0)// 协议长度 << uint32(1) << uint32(0); // 加入字符串数据(uint8表示字符串长度所占字节,此处为1字节) packet.AppendPacketString<uint8>(std::string("aaa:88889083:d5956683c17d7e284d33ee295b277b52")); // 设置协议长度 packet.SetLength(packet.size()); // 发送数据 sSocketMgr.SendPacket(1, &packet); ///
回调函数例子:
1 // 注册单个协议回调函数(样例),参数:SOCKET_ID标识,数据包 2 void process_login(int _tag, WorldPacket & packet); 3 // 注册单个协议回调函数(样例),参数:SOCKET_ID标识,协议头,数据包 4 bool process_all(int _tag, int _cmd, WorldPacket & packet); 5 // 断线事件 6 void onDisconnect(int _tag);
取数据例子:
WorldPacket packet ;
// 取整形数据 uint16 opcode; uint16 len; uint32 serial; float fl;
packet >> opcode; packet >> len; packet >> serial; packet >> fl;
// 取字符串 String oldPwd, newPwd; packet.GetPacketString<uint8>(&packet, oldPwd); packet.GetPacketString<uint8>(&packet, newPwd);
写得比较草,如果看不懂的,好的建议和意见可以给我留言。
如果有不同的,好的思路也可以提出来,一起探讨。。