客户端的网络连接请求在下列位置进入业务处理:
void TC\_EpollServer::NetThread::run() {
? ? ? ? ......
? ? ? ??? ? ?case ET\_NET:
??????????????????? //网络请求
??????????????????? processNet(ev);
??????????????????? break;
? ? ? ? ......
}
(参考:Tars-cpp源码走读——网络模块初始化和网络连接处理)](/developer/article/1377231%29%29)
通过ev.data.u32;
可以取得客户端连接的socket,从而能在制定客户端连接上读写数据。
对于网络请求,processNet(ev);处理代码如下:
??? if(ev.events & EPOLLIN) //有数据需要读取
??? {
??????? recv\_queue::queue\_type vRecvData;
??????? int ret = recvBuffer(cPtr, vRecvData);
??????? if(ret < 0)
??????? {
??????????? delConnection(cPtr,true,EM\_CLIENT\_CLOSE);
??????????? return;
??????? }
??????? if(!vRecvData.empty())
??????? {
??????????? cPtr->insertRecvQueue(vRecvData);
??????? }
??? }
先是通过recvBuffer
从指定连接上读取数据, 然后通过cPtr->insertRecvQueue(vRecvData);
把数据放在一个数据队列中,cPtr->insertRecvQueue(vRecvData);
最终会通过\_handleGroup->monitor.notify();
来通知真正的处理例程来处理业务逻辑。
void TC\_EpollServer::BindAdapter::insertRecvQueue(const recv\_queue::queue\_type &vtRecvData, bool bPushBack)
{
??? {
??????? if (bPushBack)
??????? {
??????????? \_rbuffer.push\_back(vtRecvData);
??????? }
??????? else
??????? {
??????????? \_rbuffer.push\_front(vtRecvData);
??????? }
??? }
??? TC\_ThreadLock::Lock lock(\_handleGroup->monitor);
??? \_handleGroup->monitor.notify();
}
**网络数据的读取:**
void TC\_EpollServer::NetThread::processNet(const epoll\_event &ev);
==>int TC\_EpollServer::NetThread::recvBuffer(TC\_EpollServer::NetThread::Connection \*cPtr, recv\_queue::queue\_type &v);
==>int TC\_EpollServer::NetThread::Connection::recv(recv\_queue::queue\_type &o)
==>int TC\_Socket::recvfrom(void \*pvBuf, size\_t iLen, struct sockaddr \*pstFromAddr, socklen\_t &iFromLen, int iFlags)
**通知handle对象**
void TC\_EpollServer::NetThread::processNet(const epoll\_event &ev)
==>void TC\_EpollServer::NetThread::Connection::insertRecvQueue(recv\_queue::queue\_type &vRecvData)
==>void TC\_EpollServer::BindAdapter::insertRecvQueue(const recv\_queue::queue\_type &vtRecvData, bool bPushBack)
==>??? \_handleGroup->monitor.notify();
业务处理模块会创建一些物业处理线程,线程会阻塞在一些条件变量上,等待唤醒。
void Application::main(int argc, char \*argv[])
==>void TC\_EpollServer::startHandle()
==>TC\_ThreadControl TC\_Thread::start()? ?//Handle 继承自TC\_Thread
==>void TC\_Thread::threadEntry(TC\_Thread \*pThread)
==>void TC\_EpollServer::Handle::run()? ?// Thread::run是虚函数,通过多态调用Handle::run()
void TC\_EpollServer::Handle::run()
调用两个函数:
void TC\_EpollServer::Handle::run()
{
??? initialize();
??? handleImp();
}
函数initialize();
负责把用户定义的业务处理函数和handle关联起来。
函数handleImp();
负责等待网络请求,以及调用处理函数。
initialize();
是一个虚函数,通过多态调用void ServantHandle::initialize()
函数handleImp();
中等待业务处理线程被唤醒,
??????? {
??????????? TC\_ThreadLock::Lock lock(\_handleGroup->monitor);
??????????? if (allAdapterIsEmpty() && allFilterIsEmpty())
??????????? {
??????????????? \_handleGroup->monitor.timedWait(\_iWaitTime);
??????????? }
??????? }
唤醒后等待网络数据到来:
bool TC\_EpollServer::BindAdapter::waitForRecvQueue(tagRecvData\* &recv, uint32\_t iWaitTime)
{
??? bool bRet = false;
??? bRet = \_rbuffer.pop\_front(recv, iWaitTime);
??? if(!bRet)
??? {
??????? return bRet;
??? }
??? return bRet;
}
在网络请求接受时,会把网络请求数据添加到_rbuffer中
至此,handle模块已经可以获取到网络请求的数据了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。