一个简单的BitTorrent客户端实现(三):同步事件分离器

关于同步事件分离器

了解ACE的同学想必都知道它使用了Reactor的设计模式,ACE开发的应用程序中,有个地方会调用eventloop,里面会不停地去轮询。当询到事件时,就将事件分发给指定的事件处理器,事件处理器里面有一些什么handle_read,handle_write之类的函数来响应事件。本程序也借鉴了这种模式,这样使程序结构上变得更加清晰,理解起来也更容易些。

同步事件分离器实现

本程序中的同步分离器基于套接字select函数实现,另外我们还监视定时器事件。
先说select吧,大家都知道select用于等待某个描述就绪,要么可写,要么可读,或者出错,select函数就会返回。为实现这一功能,我们需要两个描述符集,一个读,另外一个写。每次select前都会先清一下描述符集再添加。下面是实现代码:

int CSelectReactor::SelectSocket()
{
    ClearFdSet();
    AddToFdSet();

    int nRet = 0;
    timeval tmval;
    tmval.tv_sec = 1;
    tmval.tv_usec = 0;

    nRet = select(m_nMaxSocketFd + 1, &m_rSet, &m_wSet, NULL, &tmval);

    if (nRet > 0)
    {
        vector<ISocket *>::iterator it = m_vecSockets.begin();
        for (; it != m_vecSockets.end(); ++it)
        {
            if (FD_ISSET((*it)->GetHandle(), &m_rSet))
            {
               int nRes = (*it)->HandleRead();
               if (nRes == -1)
               {
                   (*it)->HandleClose();
                   (*it)->SetReactor(NULL);
                   (*it)->Close();
                   continue;
               }
            }

            if (FD_ISSET((*it)->GetHandle(), &m_wSet))
            {
                int nRes = (*it)->HandleWrite();
                if (nRes == -1)
                {
                    (*it)->HandleClose();
                    (*it)->SetReactor(NULL);
                    (*it)->Close();
                    continue;
                }
            }
        }

    }

    return nRet;
}

当有事件来临时,我们转到相应的事件处理函数,如HandleRead和HandleWrite,事件处理函数里面具体的实现逻辑,后面作详细介绍。
关于定时器事件,是在UpdateTimerList函数中实现的。我们需要维护一个定时器队列,把要监视的事件加入到队列中。时间到了会调用指定pCallback的OnTimer事件处理函数。

void CSelectReactor::UpdateTimerList()
{
    list<TimerInfo>::iterator it = m_lstTimerInfo.begin();

    for (; it != m_lstTimerInfo.end(); )
    {
        if (it->bRemove == true)
        {
            m_lstFreeTimerID.push_back(it->nTimerID);
            it = m_lstTimerInfo.erase(it);
            continue;
        }

        if (GetTickCount() >= it->llLastshotTick + it->nInterval)
        {
            it->pCallback->OnTimer(it->nTimerID);
            it->llLastshotTick = GetTickCount();

            if(it->bOneShot)
            {
                m_lstFreeTimerID.push_back(it->nTimerID);
                it = m_lstTimerInfo.erase(it);
                continue;
            }
        }

        ++it;
    }

这两件事情都是在另外一个线程中做的,当任务启动时,会创建线程,里面就会做这个事情。
程序源代码下载地址:http://download.csdn.net/detail/zxywd/9415711

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值