不同包客户端的处理方法
对于那种事件类型的
连接上了,连接失败了,断开连接了
bool NGP::OnConnected()
{
std::lock_guard<std::mutex> lock(m_PktMutex);//加锁是因为runonce应该是另一个线程
m_queFunctions.push(std::bind(&NGP::Connect2ServerSuccess, this));//对于这种传递function,其实就跟函数指针差不多,
return true;
}
bool NGP::OnRec(void* pBuffer, int nSize)//这个是专门针对包的
{
date_pkt pkt;
pkt.len = nSize;
pkt.date = new char[nSize];
memcpy(pkt.date, pBuffer, nSize);
{
std::lock_guard<std::mutex> lock(m_PktMutex);
m_quePktQueue.push(pkt);
}
return true;
}
bool NGP::OnConnectFailed()
{
std::lock_guard<std::mutex> lock(m_PktMutex);
m_queFunctions.push(std::bind(&NGP::Connect2ServerFailed, this));
return true;
}
bool NGP::OnDisconnected()//对于这个为什么不加锁,不太明白
{
m_queFunctions.push(std::bind(&NGP::Disconnected, this));
return true;
}
void NGP::RunOnce()
{
m_spTimerFac->driveTimer();
//先检查一下其他命令
if(m_queFunctions.size())
{
for (;;)
{
std::function<void()> fun;
{
std::lock_guard<std::mutex> lock(m_PktMutex);
fun = m_queFunctions.front();
}
fun();//通过里面的函数指针直接调用
{
std::lock_guard<std::mutex> lock(m_PktMutex);
m_queFunctions.pop();
}
if(0 == m_queFunctions.size())
break;
}
}
//检查数据包,一次最少处理10个命令
for (int i = 0; i < 20; i++)
{
if (m_quePktQueue.size() == 0)
break;
date_pkt pkt;
{
std::lock_guard<std::mutex> lock(m_PktMutex);
pkt = m_quePktQueue.front();
m_quePktQueue.pop();
}
ProcessDate(pkt.date, pkt.len);
delete[] pkt.date;
}
//_TcpLink->run_one();
}
void NGP::ProcessDate(void* pData, int nLen)
{
Protocol pt = {0};
if (!pt.from_buffer(pData, nLen))//解包到pt中
{
return ;
}
auto it = m_mapPktAnalysis.find(pt.cmd_type);
if(it == m_mapPktAnalysis.end())
{
std::wstring str = L"收到未绑定解析函数的命令: ";
str += boost::lexical_cast<std::wstring>((short)pt.cmd_type);
MessageBox(NULL, str.c_str(), L"收到未知命令", MB_OK);
::TerminateProcess(GetCurrentProcess(), 0);
//TerminateProcess终止指定进程及其所有线程。GetCurrentProcess()是个伪句柄
//只要当前进程需要一个进程句柄,就可以使用这个伪句柄。该句柄可以复制,但不可继承。不必调用CloseHandle函数来关闭这个句柄
}
it->second(pt.content, pt.size);
}
auto it = m_mapPktAnalysis.find(pt.cmd_type);
对于这种方式服务器用的很多
std::map<int, std::function<void(void* data, int len)> > m_mapPktAnalysis;一个协议,对应一个函数指针
基本都是在构造函数里面将其对应好,然后等包到的时候,根据这个map调用不同的函数
这种function的用法是在本类里面绑定好,然后根据不同协议直接调用,还有一种是直接在头文件里面定义function,看看咋回事
这种用法开始是在ngp里面,对于上面是调用本模块的函数,对于这种是调用别的模块的函数
struct FUN
{
std::function<> a;
std::function<> b;
std::function<> c;
};
class A
{
public:
A::A()
{
FUN fun;
fun.a = std::bind();
fun.b = std::bind();
fun.c = std::bind();
P->Init();
}
B* P
};
class B
{
public:
FUN m_fun;//项目里面作为成员变量
Init(FUN& fun)//实现调用初始化函数
{
m_fun = fun;
}
};
看来function的两种用法就是这样了
NGP就是根据发过来的协议(包),事件调用客户端绑定好的函数