zoukankan      html  css  js  c++  java
  • Simple IOCP Server代码解读

    1,如何处理乱序。

    按照投递Read的次序,收到ReadComplete时,看收到的buffer中序号跟连接中的序号是否相等。

    不如用例子表示:
    b1,b2表示两个Read请求用的buffer。连接Context中序列号为0,b1保存的序号为0,b2保存的序号为1.
    p2,p1表示先收到第二个Read的反馈,p2对应的buffer为b2,里面的序号为1,而连接Context中的序号还是0,所以暂时不处理,将buffer缓冲起来。
    等p1到达,p1对应的buffer为b1,里面的序号为0,而连接中的序号是0,处理,再将连接序号+1,由于处理是在一个while循环中,继续查找序号为1的buffer,找到后,处理。
    如此这般就能实现对buffer的乱序处理。

    if(m_bReadInOrder)
            pOverlapBuff=GetNextReadBuffer(pContext,pOverlapBuff);

            while(pOverlapBuff!=NULL)
            {
                //TRACE("R> %i\r\n",pOverlapBuff->GetSequenceNumber());

                // Mark that we are Using the buffer..
                pOverlapBuff->Use(dwIoSize);
                ProcessPackage(pContext,dwIoSize,pOverlapBuff);
                IncreaseReadSequenceNumber(pContext);
                pOverlapBuff=NULL;
                if(m_bReadInOrder)
                    pOverlapBuff=GetNextReadBuffer(pContext);
            }

    }

     

    2,如何提升读取性能。

    一个新的客户端连上后,先通过ARead()投递0字节IOInitialize事件给IOCP端口。

    当IOCP端口上收到该IOInitialize事件后(自产自销?),又干了这个:

        AZeroByteRead(pContext,pOverlapBuff);                           // 投递(PostQueuedCompletionStatus)一个0字节IOZeroByteRead事件。
        // m_iNumberOfPendlingReads=1 by default.
        for(int i=0;i<m_iNumberOfPendlingReads;i++)
        {
            EnterIOLoop(pContext); // One for each Read Loop
            ARead(pContext);                                                     // 投递(PostQueuedCompletionStatus)n个0字节IORead事件。
        }

    当IOCP端口上收到IOZeroByteRead事件后,会将buffer类型设置成IOZeroReadCompleted,触发读取(WSARecv)缓冲区长度设为0的包。

    当IOCP端口上收到IOZeroReadCompleted事件后,会重新调用AZeroByteRead(),如此循环往复。

     

    在IOCP端口上收到IORead事件后,将buffer类型设置成IOReadCompleted,然后动真格的,触发读取(WSARecv)缓冲设为真正buffer长度。

    当IOCP端口上收到IOReadCompleted事件后,继续调用ARead(pContext),如此循环往复,保持m_iNumberOfPendlingReads个读请求。

     

    1,上面连续投递n个,是为了提高吞吐率,当正在处理一个数据包时,还可以同时接收数据。

    2,没有直接投递IOReadCompleted,而是先Post IORead,马上再WSARecv IOReadCompleted,是为了将大任务分解成小任务,符合IOCP的特点。

    3,循环投递IOZeroByteRead,是为了将投递的IOReadCompleted缓冲区解锁。看下面链接:

    http://topic.csdn.net/u/20100209/10/0271d94f-0785-427b-85f5-51fe7417d22d.html

     

    3,如何处理分包。

    看ProcessPackage代码即可。

     

    4,如何处理Context非法访问。

    在一个连接中,你知道要关闭该连接,并关闭,但同时有几个IORead请求已经发出,不可避免的,它们马上返回IOCP消息,但你已经不能再访问消息中的Context对象了。

    解决办法,给Context增加计数器,当最后一个IORead返回(不论成功或失败)时,计数器肯定等于0,这时才能释放资源。

    但我的疑问是:IOCP请求和IOCP事件是一一对应的吗?客户端主动关闭时,会不会发生多余的IOCP事件。看代码,看TriggerRecv的时机对不对。

    5,有害的大包设计。

    6,转发服务器只要读取时处理乱序、分包,发送不必关心。

  • 相关阅读:
    iOS input被键盘遮挡
    js解析xml出现的问题总结
    Java——操作Excel表格,读取表格内容
    进销存管理系统——代码架构
    转换机和路由器工作原理
    考勤系统代码分析——主页布局easyui框架
    考勤系统——代码分析datagrid
    测试知识整理——基础篇
    Base64编码原理分析
    考勤系统——代码分析
  • 原文地址:https://www.cnblogs.com/tara/p/2451868.html
Copyright © 2011-2022 走看看