📄 packageserver.h
字号:
#ifndef INCLUDED_PACKAGESERVER
#define INCLUDED_PACKAGESERVER
#if defined(HAS_PRAGMA_ONCE)
#pragma PRAGMA_ONCE_DECLARE
#endif
#include "tcpserver.h"
#include "packagebase.h"
namespace acl
{
template<typename PackageType>
class PackageServer : public TcpServer // server
, public PackageBase<PackageType> // queue support
{
public:
PackageServer()
: PackageBase<PackageType>(QUEUE_SIZE)
{
}
PackageServer(u_short port, const char *addr = NULL)
: TcpServer(port, addr)
, PackageBase<PackageType>(QUEUE_SIZE)
{
}
// convert stream into package, and put into queue
bool queueStream(unsigned int clientId, protocol::BaseStream &stream)
{
PackageType *pkg = new PackageType;
pkg->setConnectId(clientId);
int startPos = 0;
if(!packageWithSize())
{
startPos = 4;
}
if(!pkg->fromStream(stream, startPos))
return false;
putPackageAtTail(pkg);
return true;
}
// send package to peer
bool sendPackage(PackageType *pkg)
{
assert(pkg);
protocol::BaseStream stream;
if(packageWithSize())
{
if(!pkg->toStream(stream))
return false;
}
else
{
// convert package to stream
protocol::BaseStream pkgStream;
int length = 0;
if(pkg->toStream(pkgStream))
{
length = pkgStream.size() - 4;
// the real stream with length indicator
stream.enc32(length);
stream += pkgStream;
}
else
{
return false;
}
}
return send(pkg->getConnectId(), stream.getBuffer(), stream.size()) == stream.size();
}
private:
//onReceive must return the following result
//RECV_OK // recv ok
//RECV_CLOSE // connection closed
//RECV_SOCKET_ERROR // socket error
//RECV_USER_ERROR // user error < 0
virtual int onReceive(const TcpClientData &client);
int recvError(int ret);
private:
enum
{
RECV_TIMEOUT = 5
};
enum
{
QUEUE_SIZE = 4096
};
enum
{
MAX_PACKAGE_LENGTH = 4096
};
};
//onReceive must return the recv result
//RECV_OK // recv ok
//RECV_CLOSE // connection closed
//RECV_SOCKET_ERROR // socket error
//RECV_USER_ERROR // user error < 0
template<typename PackageType>
int PackageServer<PackageType>::onReceive(const TcpClientData &client)
{
protocol::BaseStream stream;
int ret;
//receive the package length at first!
const AcceptedSocket &comm = client.m_socketid;
stream.resize(4);
ret = comm.recvAsyn(stream.getWriteBuffer(), stream.size(), RECV_TIMEOUT);
//check valid header
if(ret != 4)
{
if(ret > 0)
{
trace(client.m_clientid, "WRN:get package length failed, "
"just received(%d) bytes\n", ret);
}
return recvError(ret);
}
//convert to host byte order
u32 length;
stream.dec32(length);
stream.reset(); // reset the decode position
u32 left = length;
if(packageWithSize())
{
left -= 4;
}
//package can't just have the length field.
if(left <= 0 || left >= MAX_PACKAGE_LENGTH)
{
trace(client.m_clientid, "WRN:invalid length(%d)\n", length);
return RECV_USER_ERROR;
}
// allocate the new buffer
stream.resize(stream.size() + left);
// receive the left package data
// "length" may include the length of header, and "left" is actually length to be received
// length minus left equal 4 if packageWithSize() is true else equal 0
ret = comm.recvAsyn(stream.getWriteBuffer(length-left), left, RECV_TIMEOUT);
if(ret != left)
{
trace(client.m_clientid, "get left package failed, want(%d) but received(%d)\n",
left, ret);
return recvError(ret);
}
traceBinary(client.m_clientid, "received following buffer:\n", stream.getBuffer(), stream.size());
if(!queueStream(client.m_clientid, stream))
{
trace(client.m_clientid, "stream error! I can't create package from it\n");
return recvError(ret);
}
return RECV_OK;
}
template<typename PackageType>
int PackageServer<PackageType>::recvError(int ret)
{
if(ret == 0)
return RECV_CLOSE;
else if(ret > 0)
return RECV_USER_ERROR;
else
return RECV_SOCKET_ERROR;
}
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -