谈谈游戏服务器的发送数据处理

简介:

发送数据处理模式的概念:

 相信每一个第一次写游戏服务器的人都会在发送数据处理这里卡主,因为相对于简单易处理的接收消息处理,发送消息的时机和驱动更加难以把握。为什么呢?我们看下套接字可读的条件:

 1: 该套接字接收缓冲区中的数据字节数大于接收低水位标记

 2: 该连接的读关闭

 3: 该套接字是一个监听套接字,并且有新的连接

 4: 该套接字上有错误处理

以上所有的条件,都可以通过注册事件来完成,并且因为都是被动触发,所以处理起来比较轻松。

那我们看看套接字可写的条件:

 1: 该套接字发送缓冲区中可用空间大于发送高水位标记

 2: 该套接字的写关闭

 3: 该套接字上有错误处理

看到套接字可写的条件我们为难了,因为我们需要发送的时候,套接字并不一定可写;而套接字可写的时候,我们未必有数据要发送,这就造成了事件的浪费,也就造成了发送数据比接收数据更难。

 

前言: 我们在这里是将网络数据的发送和接收放在单独的线程里面处理,称之为网络IO线程;而在其他的线程总处理玩家逻辑,称之为玩家逻辑线程。

 

解决方案1: 定时发送。

定时发送算是一个比较通用的处理,也是用起来比较方便的方式。对于每一个来自客户端的连接,我们只是注册可读事件,而不会注册可写事件,对于发送处理,我们采用定时器触发的模式,比如每一个连接上绑定一个30ms的定时器,每次定时器触发的时候,也就是写饥饿的时候,对每个连接都去做一次试图发送的处理。

当大家看到思路的时候,我想麻烦也就跟着来了。因为是30ms的定时器,所以每条消息的延迟都是N*30ms;可能很多的套接字并没有数据要发送,但是定时器到了,造成了很多浪费;因为定时器的触发也是轮训的模式,大家不是都说“轮训就是强奸吗”。

 

解决方案2: 按需注册write事件

 如果我们真正了解write事件,就应该按需注册write事件。每次发送玩家数据的时候,如果只发送了部分数据,则把剩余的数据存放到自定义缓冲区,并且注册write写事件;这个事件会在下一次select的时候触发,触发的时候发送剩余的数据,如果发送完毕,就关闭write事件。

 这里我们分开网络io线程和游戏逻辑线程,如果是网络io线程内部发送数据,那么很简单,只需要调用提供send函数就可以了。如果是游戏逻辑线程里发送数据,就会稍微麻烦一点。为了保证线程的安全性以及数据的完整性,在游戏逻辑线程里面调用发送数据的接口,实际的工作是在网络线程里面完成。简单来说就是将这个函数或者task,投递到网络io线程里面去执行。

我们可以参考下muduo的做法,如果是在非网络io线程里面发送数据,就将要发送的套接字和数据封装成Functor,投递到网络io线程中去,并且唤醒网络IO线程,去处理这些需要执行的Functors(std::vector<Functor>)。

我在修改自己的网络发送模式的时候,也是这个思路,不过是用的是java为多线程提供的FutureTask,如果是在非网络io线程中发送数据,就将需要发送的连接和数据封装成FutureTask,投递到网络Io线程中去,唤醒io线程,处理需要执行的FutureTasks(Vector<FutureTask>)。

好吧,最后还是承认,其实在设计的时候,参考了一下mina的设计,不过看到muduo网络库居然和mina 的设计如此类似,相比muduo的设计也是参考了mina的设计。

 

可能很多人认为方案2的方案,会增加系统调用。因为我们不是总说要减少系统调用吗。这也是定时器发送数据模式的依据,可是我们的tcp已经提供了negle算法,大部分send的函数,只是将数据写入到缓冲区,并没有那么大的消耗。大家可以测试看下!

相关文章
|
算法 Java 数据库
一张流程图带你学会SpringBoot结合JWT实现登录功能(二)
一张流程图带你学会SpringBoot结合JWT实现登录功能
284 0
|
机器学习/深度学习 传感器 算法
【KELM分类】基于哈里斯算法优化核极限学习机HHO-KELM实现数据分类附matlab代码
【KELM分类】基于哈里斯算法优化核极限学习机HHO-KELM实现数据分类附matlab代码
|
JavaScript 前端开发
📕 重学JavaScript: 需要注意哪些方法是浅拷贝,不要在代码中滥用?
嗨,大家好!这里是`道长王jj`~ 🎩🧙‍♂️ 今天来和大家聊聊关于浅拷贝的相关知识。
173 0
|
Python
Python模块和包的基本使用
Python模块和包的基本使用
232 0
|
安全 关系型数据库 Linux
在VMware Workstation软件内,使用CentOS 7系统搭建私人云盘owncloud
在VMware Workstation软件内,使用CentOS 7系统搭建私人云盘owncloud
409 0
|
存储 数据可视化 网络协议
ElasticStack常用工具:ElasticSearch、Kibana、Beats、Logstash
ElasticStack常用工具:ElasticSearch、Kibana、Beats、Logstash
115 0
|
SQL 弹性计算 运维
冬季实战营第五期学习报告
第一个场景里u.txt文件各行分隔符不统一,有tab的,有空格的,导入以后大量空列,需要编辑后才能正常体验。
303 0
冬季实战营第五期学习报告
|
存储 C++
学习C++笔记252
C++ 日期 & 时间
179 0
|
设计模式 前端开发 NoSQL
设计模式的一些概念
目的:为什么要学习设计模式 提高复杂代码的设计和开发能力。让读源码、学框架事半功倍。 为你的职场发展做铺垫。为了应付面试, 更有竞争力。
231 0