2014 -1-6
(1)在自己的epoll的网络库中一个网络线程 然后 外部一个逻辑线程 在网络线程接受到到数据拿出一个完整的消息给逻辑线程是 开始的想法是把对应的此连接的handler指针放在数据结构体中传给逻辑线程,觉得自己这样的方法简单,公司的库中却是传的id,然后查找得到,觉得自己的处理方式简单,公司的复杂
反例 如下:
1:网络线程解析出一个完整的消息包 将消息和epoll_handler 指针封装传给 和 逻辑线程传数据的队列
2:逻辑线程一直在循环取出队列中的数据处理 此时还没处理到最新加入的数据
3:客户端主动关闭 或者 epoll检查到可写去写入数据确失败等情况需要关闭链接 删除handler
4:逻辑线程从队列中获取到了被删除的hangler的指针 此时 handler已经是一个野指针 然后使用handler发送数据 宕机
所以解决方法:
在传出的的时候只能传出 连接id或其他标识 hangler 的指针只能由handler_mgr之类的管理起来 但是网络库删除 和 逻辑线程使用hander发送数据时的查找使用, 两个线程同时操作 致使需要加锁, 此时加锁本身并不太消耗cpu 而且玩家下线或者网络断开是少量操作 所以这个锁并不太影响效率
注意: 在释放handler的时候 想把它统一放到逻辑线程 但是这违反了哪里申请 哪里释放的规则,还有一点 逻辑线程去操作网络线程的接口 一边在epoll_wait 一边还在用epoll_ctl 去删除 影响未知 也有可能刚出现上面那种网络线程把数据刚放到队列中去 然后逻辑线程删掉hangler 然后此时放进去的handler是个野指针。
总结 这就像在游戏中如果十秒后要对几个怪物做出什么处理, 此时只能把怪物id 的集合放到定时器中 然后时间到了 通过id 查找怪物去处理 千万不能传出怪物的指针集合,因为怪物随时有可能是被杀死的, 所以在项目中如果在不是线程顺序处理的情况下传指针,传唯一标识id
(2)在一个网络线程一个逻辑线程的网络库中 自己的网络线程解析到一个完整的消息包后放到和逻辑线程共享的队列后 由逻辑线程取出处理消息
但是如果逻辑线程处理完一个消息后需要给客户端返回一个消息呢? 我开始的想法是直接使用问题一种的handler_mgr 通过唯一id 找到handler 去发送,
但是这时候问题来了!!!!!!逻辑线程在利用sock发送数据, 网络线程epoll_wait 在发现此sock可写 然后进入写状态发送缓冲区的数据, 两个线程同时操作sock的send
所以此时还需要一个队列让逻辑线程put 要发送的数据,网络线程中的epoll_wait 加超时 讲发送队列的数据发送出去 所以这时候一个封装出一个双向管道 : 包含两个队列 这个管道应该是个单例 让网络线程和逻辑线程都可以读写;
总结: 跟网络收发所有的东西都应该放在网络线程中, 这就是多线程对同一个操作操作时候 如果在不加锁的情况下 应该放在一个线程里面