声明:本文参考了langresser发布的blog“跨平台的游戏客户端Socket封装

Socket处理是异步非阻塞的,所以可以放心的放到主线程处理消息,并且在原作者的基本上进行了系列优化,考虑了客户端可能建立多个SOCKET,因此加入了Manager概念,与cocos2d-x进行了融合。

本文基于cocos2d-x3.0+VS2012

点击下载:network.zip

文件目录结构截图:

文件源码:

TCPSocket.h

 #ifndef __CC_TCPSOCKET_H__
#define __CC_TCPSOCKET_H__ #include "cocos2d.h"
#include "ExtensionMacros.h"
#include "WorldPacket.h"
#ifdef WIN32
#include <windows.h>
#include <WinSock.h>
#pragma comment( lib, "ws2_32.lib" )
#else
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define SOCKET int
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1 #endif NS_CC_EXT_BEGIN
#ifndef CHECKF
#define CHECKF(x) \
do \
{ \
if (!(x)) { \
log_msg("CHECKF", #x, __FILE__, __LINE__); \
return ; \
} \
} while ()
#endif #define _MAX_MSGSIZE 16 * 1024 // 暂定一个消息最大为16k
#define BLOCKSECONDS 30 // INIT函数阻塞时间
#define INBUFSIZE (64*1024) //? 具体尺寸根据剖面报告调整 接收数据的缓存
#define OUTBUFSIZE (8*1024) //? 具体尺寸根据剖面报告调整。 发送数据的缓存,当不超过8K时,FLUSH只需要SEND一次 class CC_DLL TCPSocket
{
public:
TCPSocket(void);
bool Create(const char* pszServerIP, int nServerPort, int tagid, int nBlockSec = BLOCKSECONDS, bool bKeepAlive = false);
bool SendMsg(void* pBuf, int nSize);
bool ReceiveMsg(void* pBuf, int& nSize);
bool Flush(void);
bool Check(void);
void Destroy(void);
SOCKET GetSocket(void) const { return m_sockClient; } int getTagID(){ return m_tag; }
private:
bool recvFromSock(void); // 从网络中读取尽可能多的数据
bool hasError(); // 是否发生错误,注意,异步模式未完成非错误
void closeSocket(); SOCKET m_sockClient; // 发送数据缓冲
char m_bufOutput[OUTBUFSIZE]; //? 可优化为指针数组
int m_nOutbufLen; // 环形缓冲区
char m_bufInput[INBUFSIZE];
int m_nInbufLen;
int m_nInbufStart; // INBUF使用循环式队列,该变量为队列起点,0 - (SIZE-1)
int m_tag;
}; typedef std::function<bool(int,int,WorldPacket&)> ProAllFunc; // 接收所有协议,自行处理,@socket标识,@协议头,@数据包,返回是否分发
typedef std::function<void(int,WorldPacket&)> ProFunc; // 接收单个协议,@socket标识,@数据包
typedef std::function<void(int)> sckFunc; // 连接成功/断开事件 #define SCT_CALLBACK_1(func, _Object) std::bind(&func,_Object, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)
#define SCT_CALLBACK_2(func, _Object) std::bind(&func,_Object, std::placeholders::_1, std::placeholders::_2)
#define SCT_CALLBACK_3(func, _Object) std::bind(&func,_Object, std::placeholders::_1)
// 创建SOCKET管理器
#define CREATE_TCPSOCKETMGR(pNode) pNode->addChild(new TCPSocketManager(), 0) class CC_DLL TCPSocketManager :
public Node
{
public:
TCPSocketManager()
{
assert(!mSingleton);
this->mSingleton = this;
// 开启update
scheduleUpdate();
};
~TCPSocketManager(){};
// 创建socket并添加到管理器
TCPSocket *createSocket(const char* pszServerIP, // IP地址
int nServerPort, // 端口
int _tag, // 标识ID
int nBlockSec = BLOCKSECONDS, // 阻塞时间ms
bool bKeepAlive = false);
// 注册协议包
void register_process(const uint16 &entry, ProFunc callback);
// 注册接收所有协议
void register_all_process(ProAllFunc callback){ _pProcess = callback; }
// 注册socket连接成功事件
void register_connect(sckFunc callback){ _pOnConnect = callback; }
// 注册socket断线事件
void register_disconnect(sckFunc callback){ _OnDisconnect = callback; } // 单独添加socket到管理器
bool addSocket(TCPSocket *pSocket);
// 删除socket
bool removeSocket(int _tag);
// 断开socket
void disconnect(int _tag);
// 获取socket
TCPSocket *GetSocket(int _tag);
// 发送消息
bool SendPacket(int _tag, WorldPacket *packet); void update(float delta); static TCPSocketManager &getSingleton(){ assert(mSingleton); return *mSingleton;} private:
ProAllFunc _pProcess;
sckFunc _pOnConnect;
sckFunc _OnDisconnect;
std::list<TCPSocket*> m_lstSocket;
std::map<uint16, ProFunc> _mapProcess;
static TCPSocketManager * mSingleton;
}; #define sSocketMgr TCPSocketManager::getSingleton()
NS_CC_EXT_END #endif //__CC_TCPSOCKET_H__

TCPSocket.cpp

#include "TCPSocket.h"
#include "support/zip_support/unzip.h" NS_CC_EXT_BEGIN
TCPSocket::TCPSocket()
{
// 初始化
memset(m_bufOutput, , sizeof(m_bufOutput));
memset(m_bufInput, , 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 == || strlen(pszServerIP) > ) {
return false;
} #ifdef WIN32
WSADATA wsaData;
WORD version = MAKEWORD(, );
int ret = WSAStartup(version, &wsaData);//win sock start up
if (ret != ) {
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=;
if(setsockopt(m_sockClient, SOL_SOCKET, SO_KEEPALIVE, (char *) &optval, sizeof(optval)))
{
closeSocket();
return false;
}
} #ifdef WIN32
DWORD nMode = ;
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, , 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 = ;
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 == || ret < ) {
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 = ;
m_nInbufStart = ;
m_nOutbufLen = ; struct linger so_linger;
so_linger.l_onoff = ;
so_linger.l_linger = ;
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 == || nSize <= ) {
return false;
} if (m_sockClient == INVALID_SOCKET) {
return false;
} // 检查通讯消息包长度
int packsize = ;
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 <= ) {
return false;
} if (m_sockClient == INVALID_SOCKET) {
return false;
} // 检查是否有一个消息(小于2则无法获取到消息长度)
if(m_nInbufLen < ) {
// 如果没有请求成功 或者 如果没有数据则直接返回
if(!recvFromSock() || m_nInbufLen < ) { // 这个m_nInbufLen更新了
return false;
}
} // 计算要拷贝的消息的大小(一个消息,大小为整个消息的第一个16字节),因为环形缓冲区,所以要分开计算
int packsize = (unsigned char)m_bufInput[m_nInbufStart+] +
(unsigned char)m_bufInput[(m_nInbufStart + ) % INBUFSIZE] * ; // 注意字节序,高位+低位 // 检测消息包尺寸错误 暂定最大16k
if (packsize <= || packsize > _MAX_MSGSIZE) {
m_nInbufLen = ; // 直接清空INBUF
m_nInbufStart = ;
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, );
if(inlen > ) {
// 有接收到数据
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, );
if(inlen > ) {
m_nInbufLen += inlen;
if (m_nInbufLen > INBUFSIZE) {
return false;
}
} else if(inlen == ) {
Destroy();
return false;
} else {
// 连接已断开或者错误(包括阻塞)
if (hasError()) {
Destroy();
return false;
}
}
}
} else if(inlen == ) {
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 <= ) {
return true;
} // 发送一段数据
int outsize;
outsize = send(m_sockClient, m_bufOutput, m_nOutbufLen, );
if(outsize > ) {
// 删除已发送的部分
if(m_nOutbufLen - outsize > ) {
memcpy(m_bufOutput, m_bufOutput + outsize, m_nOutbufLen - outsize);
} m_nOutbufLen -= outsize; if (m_nOutbufLen < ) {
return false;
}
} else {
if (hasError()) {
Destroy();
return false;
}
} return true;
} bool TCPSocket::Check(void)
{
// 检查状态
if (m_sockClient == INVALID_SOCKET) {
return false;
} char buf[];
int ret = recv(m_sockClient, buf, , MSG_PEEK);
if(ret == ) {
Destroy();
return false;
} else if(ret < ) {
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 = ;
so_linger.l_linger = ;
int ret = setsockopt(m_sockClient, SOL_SOCKET, SO_LINGER, (const char*)&so_linger, sizeof(so_linger)); closeSocket(); m_sockClient = INVALID_SOCKET;
m_nInbufLen = ;
m_nInbufStart = ;
m_nOutbufLen = ; memset(m_bufOutput, , sizeof(m_bufOutput));
memset(m_bufInput, , sizeof(m_bufInput));
} TCPSocketManager *TCPSocketManager::mSingleton = ;
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] = {};
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[] = {};
uLong uncomprLen;
_cmd &= 0x7fff;
uncompress(uncompr, &uncomprLen, packet.contents()+, packet.size()-);
} if (_pProcess == || _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  (读写数据包)

 /****************************************************************************
*
* ByteBuffer Class
*
*/ #ifndef _BYTEBUFFER_H
#define _BYTEBUFFER_H #include "Common.h"
//#include "Vector3.h" class ByteBuffer
{
#define DEFAULT_SIZE 0x1000
#define DEFAULT_INCREASE_SIZE 200
uint8 * m_buffer;
size_t m_readPos;
size_t m_writePos;
uint32 m_buffersize; public:
/** Creates a bytebuffer with the default size
*/
ByteBuffer()
{
m_buffer =;
m_readPos = m_writePos = ;
m_buffersize = ;
reserve(DEFAULT_SIZE);
} /** Creates a bytebuffer with the specified size
*/
ByteBuffer(size_t res)
{
m_buffer =;
m_readPos = m_writePos = ;
m_buffersize = ;
reserve(res);
} /** Frees the allocated buffer
*/
~ByteBuffer()
{
free(m_buffer);
} /** Allocates/reallocates buffer with specified size.
*/
void reserve(size_t res)
{
if(m_buffer)
m_buffer = (uint8*)realloc(m_buffer, res);
else
m_buffer = (uint8*)malloc(res); m_buffersize = res;
} /** Resets read/write indexes
*/
inline void clear()
{
m_readPos = m_writePos = ;
} /** Sets write position
*/
inline void resize(size_t size)
{
m_writePos = size;
} /** Returns the buffer pointer
*/
inline const uint8 * contents()
{
return m_buffer;
} /** Gets the buffer size.
*/
uint32 GetBufferSize() { return m_writePos; } /** Reads sizeof(T) bytes from the buffer
* @return the bytes read
*/
template<typename T>
T Read()
{
if(m_readPos + sizeof(T) > m_writePos)
return (T);
T ret = *(T*)&m_buffer[m_readPos];
m_readPos += sizeof(T);
return ret;
} void skip(size_t len)
{
if(m_readPos + len > m_writePos)
len = (m_writePos - m_readPos);
m_readPos += len;
} /** Reads x bytes from the buffer
*/
void read(uint8 * buffer, size_t len)
{
if(m_readPos + len > m_writePos)
len = (m_writePos - m_readPos); memcpy(buffer, &m_buffer[m_readPos], len);
m_readPos += len;
} /** Writes sizeof(T) bytes to the buffer, while checking for overflows.
* @param T data The data to be written
*/
template<typename T>
void Write(const T & data)
{
size_t new_size = m_writePos + sizeof(T);
if(new_size > m_buffersize)
{
new_size = (new_size / DEFAULT_INCREASE_SIZE + ) * DEFAULT_INCREASE_SIZE;
reserve(new_size);
} *(T*)&m_buffer[m_writePos] = data;
m_writePos += sizeof(T);
} /** writes x bytes to the buffer, while checking for overflows
* @param ptr the data to be written
* @param size byte count
*/
void Write(const uint8 * data, size_t size)
{
size_t new_size = m_writePos + size;
if(new_size > m_buffersize)
{
new_size = (new_size / DEFAULT_INCREASE_SIZE + ) * DEFAULT_INCREASE_SIZE;
reserve(new_size);
} memcpy(&m_buffer[m_writePos], data, size);
m_writePos += size;
} /** Ensures the buffer is big enough to fit the specified number of bytes.
* @param bytes number of bytes to fit
*/
inline void EnsureBufferSize(uint32 Bytes)
{
size_t new_size = m_writePos + Bytes;
if(new_size > m_buffersize)
{
new_size = (new_size / DEFAULT_INCREASE_SIZE + ) * DEFAULT_INCREASE_SIZE;
reserve(new_size);
} } /** These are the default read/write operators.
*/
#define DEFINE_BUFFER_READ_OPERATOR(type) void operator >> (type& dest) { dest = Read<type>(); }
#define DEFINE_BUFFER_WRITE_OPERATOR(type) void operator << (const type src) { Write<type>(src); } /** Fast read/write operators without using the templated read/write functions.
*/
#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; } }
#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; } /** Integer/float r/w operators
*/
DEFINE_FAST_READ_OPERATOR(uint64, );
DEFINE_FAST_READ_OPERATOR(uint32, );
DEFINE_FAST_READ_OPERATOR(uint16, );
DEFINE_FAST_READ_OPERATOR(uint8, );
DEFINE_FAST_READ_OPERATOR(int64, );
DEFINE_FAST_READ_OPERATOR(int32, );
DEFINE_FAST_READ_OPERATOR(int16, );
DEFINE_FAST_READ_OPERATOR(int8, );
DEFINE_FAST_READ_OPERATOR(float, );
DEFINE_FAST_READ_OPERATOR(double, ); DEFINE_FAST_WRITE_OPERATOR(uint64, );
DEFINE_FAST_WRITE_OPERATOR(uint32, );
DEFINE_FAST_WRITE_OPERATOR(uint16, );
DEFINE_FAST_WRITE_OPERATOR(uint8, );
DEFINE_FAST_WRITE_OPERATOR(int64, );
DEFINE_FAST_WRITE_OPERATOR(int32, );
DEFINE_FAST_WRITE_OPERATOR(int16, );
DEFINE_FAST_WRITE_OPERATOR(int8, );
DEFINE_FAST_WRITE_OPERATOR(float, );
DEFINE_FAST_WRITE_OPERATOR(double, ); /** boolean (1-byte) read/write operators
*/
DEFINE_FAST_WRITE_OPERATOR(bool, );
ByteBuffer& operator >> (bool & dst) { dst = (Read<char>() > ? true : false); return *this; } /** string (null-terminated) operators
*/
ByteBuffer& operator << (const std::string & value) { EnsureBufferSize(value.length() + ); memcpy(&m_buffer[m_writePos], value.c_str(), value.length()+); m_writePos += (value.length() + ); return *this; }
ByteBuffer& operator >> (std::string & dest)
{
dest.clear();
char c;
for(;;)
{
c = Read<char>();
if(c == ) break;
dest += c;
}
return *this;
} /** Gets the write position
* @return buffer size
*/
inline size_t size() { return m_writePos; } /** read/write position setting/getting
*/
inline size_t rpos() { return m_readPos; }
inline size_t wpos() { return m_writePos; }
inline void rpos(size_t p) { assert(p <= m_writePos); m_readPos = p; }
inline void wpos(size_t p) { assert(p <= m_buffersize); m_writePos = p; } template<typename T> size_t writeVector(std::vector<T> &v)
{
for (typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); i++) {
Write<T>(*i);
}
return v.size(); }
template<typename T> size_t readVector(size_t vsize, std::vector<T> &v)
{ v.clear();
while(vsize--) {
T t = Read<T>();
v.push_back(t);
}
return v.size();
} template<typename T> size_t writeList(std::list<T> &v)
{
for (typename std::list<T>::const_iterator i = v.begin(); i != v.end(); i++) {
Write<T>(*i);
}
return v.size(); }
template<typename T> size_t readList(size_t vsize, std::list<T> &v)
{ v.clear();
while(vsize--) {
T t = Read<T>();
v.push_back(t);
}
return v.size();
} template <typename K, typename V> size_t writeMap(const std::map<K, V> &m)
{
for (typename std::map<K, V>::const_iterator i = m.begin(); i != m.end(); i++) {
Write<K>(i->first);
Write<V>(i->second);
}
return m.size();
} template <typename K, typename V> size_t readMap(size_t msize, std::map<K, V> &m)
{
m.clear();
while(msize--) {
K k = Read<K>();
V v = Read<V>();
m.insert(make_pair(k, v));
}
return m.size();
} }; ///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// template <typename T> ByteBuffer &operator<<(ByteBuffer &b, const std::vector<T> & v)
{
b << (uint32)v.size();
for (typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); i++) {
b << *i;
}
return b;
} template <typename T> ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v)
{
uint32 vsize;
b >> vsize;
v.clear();
while(vsize--) {
T t;
b >> t;
v.push_back(t);
}
return b;
} template <typename T> ByteBuffer &operator<<(ByteBuffer &b, const std::list<T> & v)
{
b << (uint32)v.size();
for (typename std::list<T>::const_iterator i = v.begin(); i != v.end(); i++) {
b << *i;
}
return b;
} template <typename T> ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v)
{
uint32 vsize;
b >> vsize;
v.clear();
while(vsize--) {
T t;
b >> t;
v.push_back(t);
}
return b;
} template <typename K, typename V> ByteBuffer &operator<<(ByteBuffer &b, const std::map<K, V> &m)
{
b << (uint32)m.size();
for (typename std::map<K, V>::const_iterator i = m.begin(); i != m.end(); i++) {
b << i->first << i->second;
}
return b;
} template <typename K, typename V> ByteBuffer &operator>>(ByteBuffer &b, std::map<K, V> &m)
{
uint32 msize;
b >> msize;
m.clear();
while(msize--) {
K k;
V v;
b >> k >> v;
m.insert(make_pair(k, v));
}
return b;
} #endif

WorldPacket.h  (读写扩展类,协议前2字节表示协议包,其次2字节表示数据大小)

 #ifndef WGSERVER_WORLDPACKET_H
#define WGSERVER_WORLDPACKET_H #include "ByteBuffer.h" class WorldPacket : public ByteBuffer
{
public:
__inline WorldPacket() : ByteBuffer(), m_opcode() { }
__inline WorldPacket(uint16 opcode, size_t res) : ByteBuffer(res), m_opcode(opcode) {}
__inline WorldPacket(size_t res) : ByteBuffer(res), m_opcode() { }
__inline WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode) {} //! Clear packet and set opcode all in one mighty blow
__inline void Initialize(uint16 opcode )
{
clear();
m_opcode = opcode;
} __inline uint16 GetOpcode() const { return m_opcode; }
__inline void SetOpcode(const uint16 & opcode) { m_opcode = opcode; }
__inline void SetLength(const uint16 & len) {
uint16 * plen = (uint16 * ) &(contents()[]);
*plen = len;
} __inline std::string getString()
{
//std::string buff =
return (const char*)contents();
} template<typename T>
void SetOffset(const uint16 & offset, const T value ) {
T * pval = (T *) &(contents()[offset]);
*pval = value;
} public:
/**
* @创建时间 2011-08-31
* @创建人 李志勇
* @函数作用 向数据包追加字符串
* @参数
* @packet 数据封包指针
* @str 追加的字符串
*/
template<typename T> void AppendPacketString(std::string str)
{
T ilen = (T)str.size();
*this << ilen;
if (ilen > )
Write((const uint8 *) str.c_str(), ilen);
}
/**
* @创建时间 2011-08-31
* @创建人 李志勇
* @函数作用 获取字符串
* @参数
* @packet 数据封包
* @返回 是否成功
*/
template<typename T> bool GetPacketString(std::string &str)
{
T ilen;
*this >> ilen;
if (ilen == )
return true;
uint8 buf[ilen+];
uint16 plen = size();
if (plen < ilen)
return false;
read(buf, ilen);
buf[ilen] = ;
str = (char*)buf;
return true;
} protected:
uint16 m_opcode;
}; /*
template<uint32 Size>
class SERVER_DECL StackWorldPacket : public StackBuffer<Size>
{
uint16 m_opcode;
public:
__inline StackWorldPacket(uint16 opcode) : StackBuffer<Size>(), m_opcode(opcode) { } //! Clear packet and set opcode all in one mighty blow
__inline void Initialize(uint16 opcode )
{
StackBuffer<Size>::Clear();
m_opcode = opcode;
} uint16 GetOpcode() { return m_opcode; }
__inline void SetOpcode(uint16 opcode) { m_opcode = opcode; }
};
*/ #endif

Common.h (bytebuffer.h所需的一些定义,该文件来自“魔兽世界服务端”源码,cocos2d-x自身有个CCommon.h文件,如果把两个文件合并的话,在linux下编译会发生冲突,冲突较多,本人也没有做区分,因此建议独立出来)

 #ifndef WGSERVER_COMMON_H
#define WGSERVER_COMMON_H #ifdef WIN32
#pragma warning(disable:4996)
#define _CRT_SECURE_NO_DEPRECATE 1
#define _CRT_SECURE_COPP_OVERLOAD_STANDARD_NAMES 1
#pragma warning(disable:4251) // dll-interface bullshit
#endif enum TimeVariables
{
TIME_SECOND = ,
TIME_MINUTE = TIME_SECOND * ,
TIME_HOUR = TIME_MINUTE * ,
TIME_DAY = TIME_HOUR * ,
TIME_MONTH = TIME_DAY * ,
TIME_YEAR = TIME_MONTH *
}; enum MsTimeVariables
{
MSTIME_SECOND = ,
MSTIME_MINUTE = MSTIME_SECOND * ,
MSTIME_HOUR = MSTIME_MINUTE * ,
MSTIME_DAY = MSTIME_HOUR *
}; #ifdef WIN32
#define WGSERVER_INLINE __forceinline
#else
#define WGSERVER_INLINE inline
#endif #ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* Define this if you're using a big-endian machine */
#ifdef USING_BIG_ENDIAN
#include <machine/byte_order.h>
#define bswap_16(x) NXSwapShort(x)
#define bswap_32(x) NXSwapInt(x)
#define bswap_64(x) NXSwapLongLong(x)
#endif #include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <math.h>
#include <errno.h>
//#include <sys/syscall.h> #if defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 )
# define WIN32_LEAN_AND_MEAN
//# define _WIN32_WINNT 0x0500
# define NOMINMAX
# include <windows.h>
#else
# include <string.h>
# define MAX_PATH
#endif #ifdef min
#undef min
#endif #ifdef max
#undef max
#endif #ifdef CONFIG_USE_SELECT
#undef FD_SETSIZE
#define FD_SETSIZE 2048
#endif #if defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 )
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <netdb.h>
#endif // current platform and compiler
#define PLATFORM_WIN32 0
#define PLATFORM_UNIX 1
#define PLATFORM_APPLE 2 #define UNIX_FLAVOUR_LINUX 1
#define UNIX_FLAVOUR_BSD 2
#define UNIX_FLAVOUR_OTHER 3
#define UNIX_FLAVOUR_OSX 4 #if defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 )
# define PLATFORM PLATFORM_WIN32
#elif defined( __APPLE_CC__ )
# define PLATFORM PLATFORM_APPLE
#else
# define PLATFORM PLATFORM_UNIX
#endif #define COMPILER_MICROSOFT 0
#define COMPILER_GNU 1
#define COMPILER_BORLAND 2 #ifdef _MSC_VER
# define COMPILER COMPILER_MICROSOFT
#elif defined( __BORLANDC__ )
# define COMPILER COMPILER_BORLAND
#elif defined( __GNUC__ )
# define COMPILER COMPILER_GNU
#else
# pragma error "FATAL ERROR: Unknown compiler."
#endif #if PLATFORM == PLATFORM_UNIX || PLATFORM == PLATFORM_APPLE
#ifdef HAVE_DARWIN
#define PLATFORM_TEXT "MacOSX"
#define UNIX_FLAVOUR UNIX_FLAVOUR_OSX
#else
#ifdef USE_KQUEUE
#define PLATFORM_TEXT "FreeBSD"
#define UNIX_FLAVOUR UNIX_FLAVOUR_BSD
#else
#define PLATFORM_TEXT "Linux"
#define UNIX_FLAVOUR UNIX_FLAVOUR_LINUX
#endif
#endif
#endif #if PLATFORM == PLATFORM_WIN32
#define PLATFORM_TEXT "Win32"
#endif #ifdef _DEBUG
#define CONFIG "Debug"
#else
#define CONFIG "Release"
#endif #ifdef USING_BIG_ENDIAN
#define ARCH "PPC"
#else
#ifdef X64
#define ARCH "X64"
#else
#define ARCH "X86"
#endif
#endif /*#if COMPILER == COMPILER_MICROSOFT
# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data
# pragma warning( disable : 4311 ) // 'type cast': pointer truncation from HMODULE to uint32
# pragma warning( disable : 4786 ) // identifier was truncated to '255' characters in the debug information
# pragma warning( disable : 4146 )
# pragma warning( disable : 4800 )
#endif*/ #if PLATFORM == PLATFORM_WIN32
#define STRCASECMP stricmp
#else
#define STRCASECMP strcasecmp
#endif #if PLATFORM == PLATFORM_WIN32
#define ASYNC_NET
#endif #ifdef USE_EPOLL
#define CONFIG_USE_EPOLL
#endif
#ifdef USE_KQUEUE
#define CONFIG_USE_KQUEUE
#endif
#ifdef USE_SELECT
#define CONFIG_USE_SELECT
#endif
#ifdef USE_POLL
#define CONFIG_USE_POLL
#endif #ifdef min
#undef min
#endif #ifdef max
#undef max
#endif #include <cstdlib>
#include <set>
#include <list>
#include <string>
#include <map>
#include <queue>
#include <sstream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
//#include <iostream> #if defined ( __GNUC__ )
# define LIKELY( _x ) \
__builtin_expect( ( _x ), )
# define UNLIKELY( _x ) \
__builtin_expect( ( _x ), )
#else
# define LIKELY( _x ) \
_x
# define UNLIKELY( _x ) \
_x
#endif #if defined (__GNUC__)
# define GCC_VERSION (__GNUC__ * \
+ __GNUC_MINOR__ * \
+ __GNUC_PATCHLEVEL__)
#endif #ifndef WIN32
#ifndef X64
# if defined (__GNUC__)
# if GCC_VERSION >=
# ifdef HAVE_DARWIN
# define __fastcall
# else
# define __fastcall __attribute__((__fastcall__))
# endif
# else
# define __fastcall __attribute__((__regparm__()))
# endif
# else
# define __fastcall __attribute__((__fastcall__))
# endif
#else
#define __fastcall
#endif
#endif #ifdef HAVE_STDCXX_0X
#include <unordered_map>
#include <unordered_set>
#elif COMPILER == COMPILER_GNU && __GNUC__ >= 3
#include <ext/hash_map>
#include <ext/hash_set>
#else
#include <hash_map>
#include <hash_set>
#endif #ifdef _STLPORT_VERSION
#define HM_NAMESPACE std
using std::hash_map;
using std::hash_set;
#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1300
#define HM_NAMESPACE stdext
using stdext::hash_map;
using stdext::hash_set;
#define ENABLE_SHITTY_STL_HACKS 1 /*
# if GNUC_COMP_VER >= 430
# define HashMap ::std::tr1::unordered_map
# define HashSet ::std::tr1::unordered_set
# else
# define HashMap ::__gnu_cxx::hash_map
# define HashSet ::__gnu_cxx::hash_set
# endif
*/ #define HashMap ::__gnu_cxx::hash_map
#define HashSet ::__gnu_cxx::hash_set // hacky stuff for vc++
#define snprintf _snprintf
#define vsnprintf _vsnprintf
//#define strlen lstrlen #ifdef WIN32
//typedef char TCHAR;
#define __T(x) x
#endif // cebernic added it
#define __utf8(x) _StringToUTF8(x)
#define __ansi(x) _StringToANSI(x)
#define __isutf8(x) _IsStringUTF8(x) #elif COMPILER == COMPILER_INTEL
#define HM_NAMESPACE std
using std::hash_map;
using std::hash_set;
#elif defined(HAVE_STDCXX_0X)
#define HM_NAMESPACE std
#define hash_map unordered_map
#define hash_set unordered_set
using std::unordered_map;
using std::unordered_set;
#elif COMPILER == COMPILER_GNU && __GNUC__ >= 3
#define HM_NAMESPACE __gnu_cxx
using __gnu_cxx::hash_map;
using __gnu_cxx::hash_set; namespace __gnu_cxx
{
template<> struct hash<unsigned long long>
{
size_t operator()(const unsigned long long &__x) const { return (size_t)__x; }
};
template<typename T> struct hash<T *>
{
size_t operator()(T * const &__x) const { return (size_t)__x; }
}; }; #else
#define HM_NAMESPACE std
using std::hash_map;
#endif /* Use correct types for x64 platforms, too */
#if COMPILER != COMPILER_GNU
typedef signed __int64 int64;
typedef signed __int32 int32;
typedef signed __int16 int16;
typedef signed __int8 int8; typedef unsigned __int64 uint64;
typedef unsigned __int32 uint32;
typedef unsigned __int16 uint16;
typedef unsigned __int8 uint8;
typedef float Real;
#else typedef int64_t int64;
typedef int32_t int32;
typedef int16_t int16;
typedef int8_t int8;
typedef uint64_t uint64;
typedef uint32_t uint32;
typedef uint16_t uint16;
typedef uint8_t uint8;
typedef uint32_t DWORD;
typedef float Real; #endif /* these can be optimized into assembly */
#ifdef USING_BIG_ENDIAN WGSERVER_INLINE static void swap16(uint16* p) { *p = bswap_16((uint16_t)*p); }
WGSERVER_INLINE static void swap32(uint32* p) { *p = bswap_32((uint32_t)*p); }
WGSERVER_INLINE static void swap64(uint64* p) { *p = bswap_64((uint64_t)*p);; } WGSERVER_INLINE static float swapfloat(float p)
{
union { float asfloat; uint8 asbytes[]; } u1, u2;
u1.asfloat = p;
/* swap! */
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[]; return u2.asfloat;
} WGSERVER_INLINE static double swapdouble(double p)
{
union { double asfloat; uint8 asbytes[]; } u1, u2;
u1.asfloat = p;
/* swap! */
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[]; return u2.asfloat;
} WGSERVER_INLINE static void swapfloat(float * p)
{
union { float asfloat; uint8 asbytes[]; } u1, u2;
u1.asfloat = *p;
/* swap! */
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
*p = u2.asfloat;
} WGSERVER_INLINE static void swapdouble(double * p)
{
union { double asfloat; uint8 asbytes[]; } u1, u2;
u1.asfloat = *p;
/* swap! */
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
u2.asbytes[] = u1.asbytes[];
*p = u2.asfloat;
} WGSERVER_INLINE static uint16 swap16(uint16 p) { return bswap_16((uint16_t)p); }
WGSERVER_INLINE static uint32 swap32(uint32 p) { return bswap_32((uint32_t)p); }
WGSERVER_INLINE static uint64 swap64(uint64 p) { return bswap_64((uint64_t)p); } WGSERVER_INLINE static void swap16(int16* p) { *p = bswap_16((uint16_t)*p); }
WGSERVER_INLINE static void swap32(int32* p) { *p = bswap_32((uint32_t)*p); }
WGSERVER_INLINE static void swap64(int64* p) { *p = bswap_64((uint64_t)*p); } WGSERVER_INLINE static int16 swap16(int16 p) { return bswap_16((uint16_t)p); }
WGSERVER_INLINE static int32 swap32(int32 p) { return bswap_32((uint32_t)p); }
WGSERVER_INLINE static int64 swap64(int64 p) { return bswap_64((uint64_t)p); } #endif
/*
Scripting system exports/imports
*/ #ifdef WIN32
#ifndef SCRIPTLIB
#define SERVER_DECL __declspec(dllexport)
#define SCRIPT_DECL __declspec(dllimport)
#else
#define SERVER_DECL __declspec(dllimport)
#define SCRIPT_DECL __declspec(dllexport)
#endif
#else
#define SERVER_DECL
#define SCRIPT_DECL
#endif // Include all threading files
#include <assert.h>
//#include "Threading/Threading.h" //#include "MersenneTwister.h" #if COMPILER == COMPILER_MICROSOFT #define I64FMT "%016I64X"
#define I64FMTD "%I64u"
#define SI64FMTD "%I64d"
#define snprintf _snprintf
#define atoll __atoi64 #else #define stricmp strcasecmp
#define strnicmp strncasecmp
#define I64FMT "%016llX"
#define I64FMTD "%llu"
#define SI64FMTD "%lld" #endif #ifndef WIN32
#ifdef USING_BIG_ENDIAN
//#define GUID_HIPART(x) (*((uint32*)&(x)))
//#define GUID_LOPART(x) (*(((uint32*)&(x))+1))
#define GUID_LOPART(x) ( ( x >> 32 ) )
#define GUID_HIPART(x) ( ( x & 0x00000000ffffffff ) )
#else
#define GUID_HIPART(x) ( ( x >> 32 ) )
#define GUID_LOPART(x) ( ( x & 0x00000000ffffffff ) )
#endif
#else
#define GUID_HIPART(x) (*(((uint32*)&(x))+1))
#define GUID_LOPART(x) (*((uint32*)&(x)))
#endif #define atol(a) strtoul( a, NULL, 10) #define STRINGIZE(a) #a // fix buggy MSVC's for variable scoping to be reliable =S
#define for if(true) for #if COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1400
#pragma float_control(push)
#pragma float_control(precise, on)
#endif // fast int abs
static inline int int32abs( const int value )
{
return (value ^ (value >> )) - (value >> );
} // fast int abs and recast to unsigned
static inline uint32 int32abs2uint32( const int value )
{
return (uint32)(value ^ (value >> )) - (value >> );
} /// Fastest Method of float2int32
static inline int float2int32(const float value)
{
#if !defined(X64) && COMPILER == COMPILER_MICROSOFT && !defined(USING_BIG_ENDIAN)
int i;
__asm {
fld value
frndint
fistp i
}
return i;
#else
union { int asInt[]; double asDouble; } n;
n.asDouble = value + 6755399441055744.0; #if USING_BIG_ENDIAN
return n.asInt [];
#else
return n.asInt [];
#endif
#endif
} /// Fastest Method of long2int32
static inline int long2int32(const double value)
{
#if !defined(X64) && COMPILER == COMPILER_MICROSOFT && !defined(USING_BIG_ENDIAN)
int i;
__asm {
fld value
frndint
fistp i
}
return i;
#else
union { int asInt[]; double asDouble; } n;
n.asDouble = value + 6755399441055744.0; #if USING_BIG_ENDIAN
return n.asInt [];
#else
return n.asInt [];
#endif
#endif
} #if COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1400
#pragma float_control(pop)
#endif #ifndef WIN32
#include <sys/timeb.h>
#endif extern uint32 system_start_time_t; WGSERVER_INLINE uint32 now()
{
#ifdef WIN32
return GetTickCount();
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return ((tv.tv_sec - system_start_time_t) * ) + (tv.tv_usec / );
#endif
} #ifndef WIN32
#define FALSE 0
#define TRUE 1
#endif #ifndef WIN32
#define Sleep(ms) usleep(1000*ms)
#endif /*#ifdef WIN32
#ifndef __SHOW_STUPID_WARNINGS__
#pragma warning(disable:4018)
#pragma warning(disable:4244)
#pragma warning(disable:4305)
#pragma warning(disable:4748)
#pragma warning(disable:4800)
#pragma warning(disable:4996)
#pragma warning(disable:4251)
#endif
#endif #undef INTEL_COMPILER
#ifdef INTEL_COMPILER
#pragma warning(disable:279)
#pragma warning(disable:1744)
#pragma warning(disable:1740)
#endif*/ //#include "Util.h"
struct WayPoint
{
WayPoint()
{
o = 0.0f;
}
uint32 id;
float x;
float y;
float z;
float o;
uint32 waittime; //ms
uint32 flags;
bool forwardemoteoneshot;
uint32 forwardemoteid;
bool backwardemoteoneshot;
uint32 backwardemoteid;
uint32 forwardskinid;
uint32 backwardskinid; }; struct spawn_timed_emotes
{
uint8 type; //1 standstate, 2 emotestate, 3 emoteoneshot
uint32 value; //get yar list elsewhere
char *msg; //maybe we wish to say smething while changing emote state
uint8 msg_type; //yell ? say ?
uint8 msg_lang; //yell ? say ?
uint32 expire_after; //going to nex faze in
};
typedef std::list<spawn_timed_emotes*> TimedEmoteList; WGSERVER_INLINE void reverse_array(uint8 * pointer, size_t count)
{
size_t x;
uint8 * temp = (uint8*)malloc(count);
memcpy(temp, pointer, count);
for(x = ; x < count; ++x)
pointer[x] = temp[count-x-];
free(temp);
} typedef std::vector<WayPoint*> WayPointMap; int32 GetTimePeriodFromString(const char * str);
std::string ConvertTimeStampToString(uint32 timestamp);
std::string ConvertTimeStampToDataTime(uint32 timestamp); uint32 DecimalToMask(uint32 dec); WGSERVER_INLINE void wgs_TOLOWER(std::string& str)
{
for(size_t i = ; i < str.length(); ++i)
str[i] = (char)tolower(str[i]);
} WGSERVER_INLINE void wgs_TOUPPER(std::string& str)
{
for(size_t i = ; i < str.length(); ++i)
str[i] = (char)toupper(str[i]);
} // returns true if the ip hits the mask, otherwise false
inline static bool ParseCIDRBan(unsigned int IP, unsigned int Mask, unsigned int MaskBits)
{
// CIDR bans are a compacted form of IP / Submask
// So 192.168.1.0/255.255.255.0 would be 192.168.1.0/24
// IP's in the 192.168l.1.x range would be hit, others not.
unsigned char * source_ip = (unsigned char*)&IP;
unsigned char * mask = (unsigned char*)&Mask;
int full_bytes = MaskBits / ;
int leftover_bits = MaskBits % ;
//int byte; // sanity checks for the data first
if( MaskBits > )
return false; // this is the table for comparing leftover bits
static const unsigned char leftover_bits_compare[] = {
0x00, //
0x80, //
0xC0, //
0xE0, //
0xF0, //
0xF8, //
0xFC, //
0xFE, //
0xFF, // 11111111 - This one isn't used
}; // if we have any full bytes, compare them with memcpy
if( full_bytes > )
{
if( memcmp( source_ip, mask, full_bytes ) != )
return false;
} // compare the left over bits
if( leftover_bits > )
{
if( ( source_ip[full_bytes] & leftover_bits_compare[leftover_bits] ) !=
( mask[full_bytes] & leftover_bits_compare[leftover_bits] ) )
{
// one of the bits does not match
return false;
}
} // all of the bits match that were testable
return true;
} inline static unsigned int MakeIP(const char * str)
{
unsigned int bytes[];
unsigned int res;
if( sscanf(str, "%u.%u.%u.%u", &bytes[], &bytes[], &bytes[], &bytes[]) != )
return ; res = bytes[] | (bytes[] << ) | (bytes[] << ) | (bytes[] << );
return res;
} inline static unsigned int GetANetwork(unsigned int ip)
{
return (ip & 0x000000FF);
} inline static unsigned int GetBNetwork(unsigned int ip)
{
return (ip & 0x0000FFFF);
} inline static unsigned int GetCNetwork(unsigned int ip)
{
return (ip & 0x00FFFFFF);
} //get current thread id
#define getThreadId() syscall(__NR_gettid) // warning, by enabling this define you are aware that you are only delaying the inevitable
// some crashes are not recorable and those will stack up in time and lead to a full crash
// enabling this define will make windows servers shut down only the map instance in where the crash ocured
// during this forced shutdown players are not saved to avoid saving corrupted data
// there might be a lot of cases where each saved crash will lead to memory leaks or unhandled cases
// crashreports are still created and do use them to report the actaul problem that casued the crash
// fixing the problem that causes the crash is the proper way to fix things
//#define FORCED_SERVER_KEEPALIVE #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", , );
// 注册协议,参数:包头,回调函数
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()// 协议长度
<< uint32()
<< uint32();
// 加入字符串数据(uint8表示字符串长度所占字节,此处为1字节)
packet.AppendPacketString<uint8>(std::string("aaa:88889083:d5956683c17d7e284d33ee295b277b52"));
// 设置协议长度
packet.SetLength(packet.size());
// 发送数据
sSocketMgr.SendPacket(, &packet);
///////////////////////////////////////////////

回调函数例子:

 // 注册单个协议回调函数(样例),参数:SOCKET_ID标识,数据包
void process_login(int _tag, WorldPacket & packet);
// 注册单个协议回调函数(样例),参数:SOCKET_ID标识,协议头,数据包
bool process_all(int _tag, int _cmd, WorldPacket & packet);
// 断线事件
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);

写得比较草,如果看不懂的,好的建议和意见可以给我留言。

如果有不同的,好的思路也可以提出来,一起探讨。。

包含到cocos2d-x里的tcpsocket源码的更多相关文章

  1. Eclipse里导入Mybatis源码工程

    打开Eclipse,在前两天的记录里我已经把Maven什么的都配置好了,还有Mybatis的源码也下载下来了,不相信的话可以去看一下我之前的记录:) OK. Mybatis源码解压之后是一个标准的Ma ...

  2. 可视化查询(sp_helptext)——快速查询包含指定字符串的存储过程(附源码)

    前言 在开发中,随着业务逻辑的调整,修改存储过程是必不可免的. 那怎么定位到需要修改的存储过程呢?一个一个的点开查询?存储过程少的话还行,一旦存储过程过多,这样是很浪费时间的,一个不注意还会遗漏掉. ...

  3. threejs里面的vector3源码解析

    // File:src/math/Vector3.js /** * @author mrdoob / http://mrdoob.com/ * @author *kile / http://kile. ...

  4. QVariant相当于一个包含大多数Qt数据类型的联合体(源码解读)

    将数据存储为一个Private结构体类型的成员变量d: <qvariant.cpp> 1 QVariant::QVariant(Type type) 2 { create(type, 0) ...

  5. VS2015 Git 源码管理工具简单入门

    1.VS Git插件 1.1 环境 VS2015+GitLab 1.2 Git操作过程图解 1.3 常见名词解释 拉取(Pull):将远程版本库合并到本地版本库,相当于(Fetch+Meger) 获取 ...

  6. (一)openwrt源码目录概述

    前言 这段时间总是在和openwrt打交道,之前也零零散散地写过一点,还是希望能有点体系.还记得我刚看到源代码的时候,觉得无从下手.我想从Makefile的整个执行过程入手,搞清楚编译源代码的几个小时 ...

  7. 躲避球游戏ios源码

    躲避球游戏源码,有限源码是一个基于cocos2d的躲避球游戏源码的,并且还引用了大家熟悉google广告的,进行推广,已经还有带game center等,游戏操作很简单,用手指按住物体,然后移动物体避 ...

  8. Solr4.8.0源码分析(3)之index的线程池管理

    Solr4.8.0源码分析(3)之index的线程池管理 Solr建索引时候是有最大的线程数限制的,它由solrconfig.xml的<maxIndexingThreads>8</m ...

  9. ASP.NET Core MVC 源码学习:MVC 启动流程详解

    前言 在 上一篇 文章中,我们学习了 ASP.NET Core MVC 的路由模块,那么在本篇文章中,主要是对 ASP.NET Core MVC 启动流程的一个学习. ASP.NET Core 是新一 ...

随机推荐

  1. c#保留小数点后两位

    double d = 23423.24234234d; Response.Write(d.ToString("0.00"));

  2. 使用IDEA自带maven建java项目时报错。

    今天用IDEA建立maven项目时报错: [INFO] Scanning for projects... [INFO] Searching repository for plugin with pre ...

  3. HashTable、HashMap、LinkedHashMap、TreeMap的比较

    HashTable:继承自Dictionary类,实现了Map接口,不允许键或值为空,线程同步: HashMap:继承自AbstractMap类,实现了Map接口,允许键或值为空,线程不同步: Lin ...

  4. c#基础精华01(强调代码规范,虚方法,抽象方法,接口)

    强调代码规范 规则(法律,必须遵守否则报错) 语法 规范(道德,大家都喜欢有道德的人.) 注释//,/**/,/// 骆驼命名 :第一个单词首字母小写,之后的单词首字母大写 userName.user ...

  5. 验证Android用户输入日期

    如何验证用户输入的日期是有效还是无效? private Pattern pattern; private Matcher matcher; private static final String DA ...

  6. Move to Another Changelist

    Move to Another Changelist 将选中的文件转移到其他的 Change list 中. Change list 是一个重要的概念,这里需要进行重点说明.很多时候,我们开发一个项目 ...

  7. 手动添加 memcached.jar包

    由于目前java memcached client没有官方的maven repository可供使用,因此使用时需要手动将其安装到本地repository. java memcached client ...

  8. android下升级软件介绍

    编译android: 生成:system.img,ramdisk.img,userdata.img映像文件. ramdisk.img是emulator的文件系统 system.img包括了主要的包.库 ...

  9. poj2482Stars in Your Window(线段树+离散化+扫描线)

    http://poj.org/problem?id=2482 类似于上一篇 这题转化的比较巧妙 将一个点转化为一个矩形(x,y, x+w,y+h),扫描线入值为正 出值为负 也就是一根线过去 每进入一 ...

  10. Android 内存管理分析(四)

    尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/8920039 最近在网上看了不少Android内存管理方面的博文,但是文章大多 ...