• IOCP


    1.IOCP自动维护worker线程,没必要将worker组织为线程池,即不采用IOCP+线程池

     

    2.

    lpCompletionKey与File Handle关联,每当File Handle上的请求完成时lpCompletionKey都会随IO完成包出现在完成队列。

    File Handle出现问题,之前投递的所有请求都会返回,如何释放lpCompletionKey堆空间?

    有做法如下,使用引用计数,外带一把锁,投递请求计数加1,请求完成计数减一,检查计数为0,则删除lpCompletionKey,删除引用计数,销毁锁。

    问题:设线程A于SOCKET s上已投递WSARecv,则s对象引用计数为1;某时刻线程B于s投递WSASend或WSARecv,投递成功、请求未完成,则B主动申请s锁以递增引用计数。若恰在此时连接被Client关闭,则A和B投递的请求均从GetQueuedCompletionStatus返回,则两者都将申请s锁以递减引用计数。假设A投递的请求返回后由线程D处理,D先与B获取到s锁,递减引用计数后值为0,则执行清理操作。D释放lpCompletionKey堆空间、释放引用计数、销毁锁,那么B将面临锁被销毁的不确定因素和之后访问引用计数带来的内存崩溃。若D仅释放lpCompletionKey,则程序长时间运行必将导致引用计数和锁资源的泄露问题。

    AlarmServer面对此问题的解决方案:

        不使用任何lpCompletionKey:CreateIoCompletionPort((HANDLE)s, hCompletionPort, NULL, 0);

        或仅传入普通变量SOCKET:CreateIoCompletionPort((HANDLE)s, hCompletionPort, s, 0);

        一切记录工作由PER_IO_DATA完成。

        切忌传入堆地址CreateIoCompletionPort((HANDLE)s, hCompletionPort, pphd, 0);势必将引入引用计数、临界区、堆释放的邪恶深渊。


    该问题的解决方法:

    对于每条连接,同时投递CPU个数的接收,设CPU个数为n。

    连接出现异常,如主动关闭或对方关闭时,处理PER_HANDLE_DATA的线程原子递增该结构中的计数器iReleaseCount。

    iReleaseCount == n,则对此结构进行清理操作。

    清理完成,此结构加入空闲列表表尾,空闲列表长度超过限定,从表头delete释放空间。


    3. 

    BOOL WINAPI GetQueuedCompletionStatus(
      _In_   HANDLE CompletionPort,
      _Out_  LPDWORD lpNumberOfBytes,
      _Out_  PULONG_PTR lpCompletionKey,
      _Out_  LPOVERLAPPED *lpOverlapped,
      _In_   DWORD dwMilliseconds
    );

    Client关闭连接的判断条件是:bRet == true && lpNumberOfBytes == 0 && OP_ACCEPT != iTypeOpt


    4. 把所有的closesocket(s)放在一个函数里面:在连接异常断开时,在该函数中添加断点,方便定位。

  • 相关阅读:
    MongoDB集群架构 调整,增加延迟备份节点服务器,删除仲裁节点(9)
    MongoDB 副本集管理-不定期更新(8)
    DML和查询操作说明(7)
    MongoDB 副本集权限认证(6)
    python之路——作业:Select FTP(仅供参考)
    python之路——作业:类Farbic主机管理程序(仅供参考)
    python之路——作业:高级FTP(仅供参考)
    python之路——RabbitMQ
    python之路——协程(greenlet、gevent、简单爬虫)
    python之路——多进程(进程间通信、进程池)
  • 原文地址:https://www.cnblogs.com/chaikefusibushiji/p/6775784.html
Copyright © 2020-2023  润新知