??xml version="1.0" encoding="utf-8" standalone="yes"?>精品91福利视频,亚洲日本在线a,免费在线看污http://www.aygfsteel.com/kuxiaoku/category/21190.html收藏zh-cnSat, 07 Apr 2007 17:56:12 GMTSat, 07 Apr 2007 17:56:12 GMT60拼包函数及网l封包的异常处理http://www.aygfsteel.com/kuxiaoku/archive/2007/04/07/109154.html苦笑?/dc:creator>苦笑?/author>Sat, 07 Apr 2007 14:07:00 GMThttp://www.aygfsteel.com/kuxiaoku/archive/2007/04/07/109154.htmlhttp://www.aygfsteel.com/kuxiaoku/comments/109154.htmlhttp://www.aygfsteel.com/kuxiaoku/archive/2007/04/07/109154.html#Feedback0http://www.aygfsteel.com/kuxiaoku/comments/commentRss/109154.htmlhttp://www.aygfsteel.com/kuxiaoku/services/trackbacks/109154.html本文作者:sodme
本文出处Q?a >http://blog.csdn.net/sodme
声明Q本文可以不l作者同意Q意{载、复制、传播,但Q何对本文的引用都请保留作者、出处及本声明信息。谢谢!

常见的网l服务器Q基本上?*24时q{的,对于|游来说Q至要求服务器要能q箋工作一周以上的旉q保证不出现服务器崩溃这LN性事件。事 实上Q要求一个服务器在连l的满负药转下不出M异常Q要求它设计的近乎完,q几乎是不太现实的。服务器本n可以出异常(但要可能少得出Q,但是Q? 服务器本w应该被设计得以健壮,“病灾”打不垮它Q这p求服务器在异常处理方面要下很多功夫?/p>

  服务器的异常处理包括的内定w常广泛,本文仅就在网l封包方面出现的异常作一讨论Q希望能Ҏ(gu)从事相关工作的朋友有所帮助?/p>

关于|络包斚w的异常,M来说Q可以分Z大类Q一是封包格式出现异常;二是包内容Q即包数据Q出现异常。在包格式的异常处理方面,我们在最 底端的网l数据包接收模块便可以加以处理。而对于封包数据内容出现的异常Q只有依靠游戏本w的逻辑d以判定和验。游戏逻辑斚w的异常处理,是随每个? 戏的不同而不同的Q所以,本文随后的内容将重点阐述在网l数据包接收模块中的异常处理?/p>

  为方便以下的讨论Q先明确两个概念Q这两个概念是ؓ了叙q方面,W者自行取的,q无标准可言Q:
  1、逻辑包:指的是在应用层提交的数据包,一个完整的逻辑包可以表CZ个确切的逻辑意义。比如登录包Q它里面可以含有用户名字段和密码字Dc尽它看上M是一D늼冲区数据Q但q个~冲区里的各个区间是代表一定的逻辑意义的?br>  2、物理包Q指的是使用recv(recvfrom)或wsarecv(wsarecvfrom)从网l底层接收到的数据包Q这h到的一个数据包Q能不能表示一个完整的逻辑意义Q要取决于它是通过UDPcȝ“数据报协?#8221;发的包还是通过TCPcȝ“协?#8221;发的包?/p>

我们知道QTCP是流协议Q?#8220;协?#8221;?#8220;数据报协?#8221;的不同点在于Q?#8220;数据报协?#8221;中的一个网l包本n是一个完整的逻辑包,也就是说Q在应用层? sendto发送了一个逻辑包之后,在接收端通过recvfrom接收到的是刚才使用sendto发送的那个逻辑包,q个包不会被分开发送,也不会与? 它的包放在一起发送。但对于TCP而言QTCP会根据网l状况和neagle法Q或者将一个逻辑包单独发送,或者将一个逻辑包分成若q次发送,或者会? 若干个逻辑包合在一起发送出厅R正因ؓTCP在逻辑包处理方面的q种_合性,要求我们在作ZTCP的应用时Q一般都要编写相应的拼包、解包代码?/p>

  因此Q基于TCP的上层应用,一般都要定义自q包格式。TCP的封包定义中Q除了具体的数据内容所代表的逻辑意义之外Q第一步就是要定以何U方式表C当前包的开始和l束。通常情况下,表示一个TCP逻辑包的开始和l束有两U方式:
  1、以Ҏ(gu)的开始和l束标志表示Q比如FF00表示开始,00FF表示l束?br>  2、直接以包长度来表示。比如可以用W一个字节表C包总长度,如果觉得q样的话包比较小Q也可以用两个字节表C包长度?/p>

  下面要l出的代码是以第2U方式定义的数据包,包长度以每个包的前两个字节表示。我结合着代码l出相关的解释和说明?/p>

  函数中用到的变量说明Q?/p>

  CLIENT_BUFFER_SIZEQ缓冲区的长度,定义为:Const int CLIENT_BUFFER_SIZE=4096?br>  m_ClientDataBufQ数据整理缓冲区Q每ơ收到的数据Q都会先被复制到q个~冲区的末尾Q然后由下面的整理函数对q个~冲行整理。它的定义是Qchar m_ClientDataBuf[2* CLIENT_BUFFER_SIZE]?br>  m_DataBufByteCountQ数据整理缓冲区中当前剩余的未整理字节数?br>  GetPacketLen(const char*)Q函敎ͼ可以Ҏ(gu)传入的缓冲区首址按照应用层协议取出当前逻辑包的长度?br>  GetGamePacket(const char*, int)Q函敎ͼ可以Ҏ(gu)传入的缓冲区生成相应的游戏逻辑数据包?br>  AddToExeList(PBaseGamePacket)Q函敎ͼ指定的游戏逻辑数据包加入待处理的游戏逻辑数据包队列中Q等待逻辑处理U程对其q行处理?br>  DATA_POSQ指的是除了包长度、包cd{这些标志型字段之外Q真正的数据包内容的起始位置?/p>

Bool SplitFun(const char* pData,const int &len)
{
    PBaseGamePacket pGamePacket=NULL;
    __int64 startPos=0, prePos=0, i=0;
    int packetLen=0;

  //先将本次收到的数据复制到整理~冲区尾?br>    startPos = m_DataBufByteCount;  
    memcpy( m_ClientDataBuf+startPos, pData, len );
    m_DataBufByteCount += len;   

    //当整理缓冲区内的字节数少于DATA_POS字节Ӟ取不到长度信息则退?br> //注意Q退出时q不|m_DataBufByteCount?
    if (m_DataBufByteCount < DATA_POS+1)
        return false; 

    //Ҏ(gu)正常逻辑Q下面的情况不可能出玎ͼ为稳妥v见,q是加上
    if (m_DataBufByteCount >  2*CLIENT_BUFFER_SIZE)
    {
        //讄m_DataBufByteCount?Q意味着丢弃~冲Z的现有数?br>        m_DataBufByteCount = 0;

  //可以考虑开N误格式数据包的处理接口,处理逻辑交给上层
  //OnPacketError()
        return false;
    }

     //q原起始指针
     startPos = 0;

     //只有当m_ClientDataBuf中的字节个数大于最包长度时才能执行此语句
    packetLen = GetPacketLen( pIOCPClient->m_ClientDataBuf );

    //当逻辑层的包长度不合法Ӟ则直接丢弃该?br>    if ((packetLen < DATA_POS+1) || (packetLen > 2*CLIENT_BUFFER_SIZE))
    {
        m_DataBufByteCount = 0;

  //OnPacketError()
        return false;
    }

    //保留整理~冲区的末尾指针
    __int64 oldlen = m_DataBufByteCount; 

    while ((packetLen <= m_DataBufByteCount) && (m_DataBufByteCount>0))
    {
        //调用拼包逻辑Q获取该~冲区数据对应的数据?br>        pGamePacket = GetGamePacket(m_ClientDataBuf+startPos, packetLen); 

        if (pGamePacket!=NULL)
        {
            //数据包加入执行队列
            AddToExeList(pGamePacket);
        }

        pGamePacket = NULL;
 
  //整理~冲区的剩余字节数和新逻辑包的起始位置q行调整
        m_DataBufByteCount -= packetLen;
        startPos += packetLen; 

        //D留~冲区的字节数少于一个正常包大小Ӟ只向前复制该包随后退?br>        if (m_DataBufByteCount < DATA_POS+1)
        {
            for(i=startPos; i<startPos+m_DataBufByteCount; ++i)
                m_ClientDataBuf[i-startPos] = m_ClientDataBuf[i];

            return true;
        }

        packetLen = GetPacketLen(m_ClientDataBuf + startPos );

         //当逻辑层的包长度不合法Ӟ丢弃该包及缓冲区以后的包
        if ((packetLen<DATA_POS+1) || (packetLen>2*CLIENT_BUFFER_SIZE))
        {
            m_DataBufByteCount = 0;

      //OnPacketError()
            return false;
        }

         if (startPos+packetLen>=oldlen)
        {
            for(i=startPos; i<startPos+m_DataBufByteCount; ++i)
                m_ClientDataBuf[i-startPos] = m_ClientDataBuf[i];          

            return true;
        }
     }//取所有完整的?/p>

     return true;
}

  以上便是数据接收模块的处理函敎ͼ下面是几点简要说明:

  1、用于拼包整理的~冲?m_ClientDataBuf)应该比recv中指定的接收~冲?pData)长度(CLIENT_BUFFER_SIZE)要大Q通常前者是后者的2?2*CLIENT_BUFFER_SIZE)或更大?br>
  2、ؓ避免因ؓ剩余数据前移而导致的额外开销Q徏议m_ClientDataBuf使用环Ş~冲区实现?br>
3、ؓ了避免出现无法拼装的包,我们U定每次发送的逻辑包,其单个逻辑包最大长度不可以过CLIENT_BUFFER_SIZE?倍。因为我们的? 理缓冲区只有2*CLIENT_BUFFER_SIZEq么长,更长的数据,我们无法整理。这p求在协议的设计上以及最l的发送函数的处理上要加上q? L异常处理机制?/p>


  4、对于数据包q短或过长的包,我们通常的情冉||m_DataBufByteCount?Q即舍弃当前 包的处理。如果此处不讄m_DataBufByteCount?也可Q但该客L只要发了一ơ格式错误的包,则其后发过来的包则也将q带着产生格式 错误Q如果设|m_DataBufByteCount?Q则可以比较好的避免后的包受此包的格式错误影响。更好的作法是,在此处开放一个封包格式异? 的处理接?OnPacketError)Q由上层逻辑军_对这U异常如何处|。比如上层逻辑可以对封包格式方面出现的异常q行计数Q如果错误的ơ数过 一定的|则可以断开该客L的连接?/p> 5、徏议不要在recv或wsarecv的函数后Q就紧接着作以上的处理。当recv收到一D| 据后Q生成一个结构体或对?它主要含有data和len两个内容Q前者是数据~冲区,后者是数据长度)Q将q样的一个结构体或对象放C个队列中由后? 的线E对其用SplitFun函数q行整理。这P可以最大限度地提高|络数据的接攉度Q不臛_为数据整理的原因而在此处费旉?img src ="http://www.aygfsteel.com/kuxiaoku/aggbug/109154.html" width = "1" height = "1" />

]]>
心情日志http://www.aygfsteel.com/kuxiaoku/archive/2007/04/01/107765.html苦笑?/dc:creator>苦笑?/author>Sun, 01 Apr 2007 07:44:00 GMThttp://www.aygfsteel.com/kuxiaoku/archive/2007/04/01/107765.htmlhttp://www.aygfsteel.com/kuxiaoku/comments/107765.htmlhttp://www.aygfsteel.com/kuxiaoku/archive/2007/04/01/107765.html#Feedback0http://www.aygfsteel.com/kuxiaoku/comments/commentRss/107765.htmlhttp://www.aygfsteel.com/kuxiaoku/services/trackbacks/107765.html

]]>
[分n]JDOM1.0的API文档QCHM版)http://www.aygfsteel.com/kuxiaoku/archive/2007/03/27/106798.html苦笑?/dc:creator>苦笑?/author>Tue, 27 Mar 2007 15:18:00 GMThttp://www.aygfsteel.com/kuxiaoku/archive/2007/03/27/106798.htmlhttp://www.aygfsteel.com/kuxiaoku/comments/106798.htmlhttp://www.aygfsteel.com/kuxiaoku/archive/2007/03/27/106798.html#Feedback0http://www.aygfsteel.com/kuxiaoku/comments/commentRss/106798.htmlhttp://www.aygfsteel.com/kuxiaoku/services/trackbacks/106798.htmlhttp://www.aygfsteel.com/Files/kuxiaoku/JDOMAPIDOCS.rar

点击下蝲


]]>
[分n]Java设计模式资料http://www.aygfsteel.com/kuxiaoku/archive/2007/03/27/106792.html苦笑?/dc:creator>苦笑?/author>Tue, 27 Mar 2007 15:07:00 GMThttp://www.aygfsteel.com/kuxiaoku/archive/2007/03/27/106792.htmlhttp://www.aygfsteel.com/kuxiaoku/comments/106792.htmlhttp://www.aygfsteel.com/kuxiaoku/archive/2007/03/27/106792.html#Feedback0http://www.aygfsteel.com/kuxiaoku/comments/commentRss/106792.htmlhttp://www.aygfsteel.com/kuxiaoku/services/trackbacks/106792.htmlC传上来大家一起分享?br>
http://www.aygfsteel.com/Files/kuxiaoku/DESIGN.rar

点击卛_下蝲?

]]>
վ֩ģ壺 | ƽ| ά| Ϊ| ٲ| | | Ϫ| ʯ| | | | Ӷ| | | ֦| ޻| | | Ӣ| | ʹ| | | żҸ| ɽ| | | ̨| | | ֶ| ̨| Ժ| | ˫| ϴ| ӱ| ű| | |