客户端处理包方法
不同包客户端的处理方法 对于那种事件类型的 连接上了,连接失败了,断开连接了 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就是根据发过来的协议(包),事件调用客户端绑定好的函数