Tars-cpp源码走读——网络模块和业务模块的数据传递

网络请求的接收

客户端的网络连接请求在下列位置进入业务处理:

void TC\_EpollServer::NetThread::run() {

        ......


             case ET\_NET:
                    //网络请求
                    processNet(ev);
                    break;


        ......


}

(参考:Tars-cpp源码走读——网络模块初始化和网络连接处理)](https://cloud.tencent.com/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模块已经可以获取到网络请求的数据了。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券