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

简介:

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

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

 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的函数,只是将数据写入到缓冲区,并没有那么大的消耗。大家可以测试看下!

相关文章
|
3月前
|
XML JSON 安全
Gob实践全攻略,数据传输利器
Gob实践全攻略,数据传输利器
38 0
|
7天前
|
消息中间件 监控 大数据
Kafka消息队列架构与应用场景探讨:面试经验与必备知识点解析
【4月更文挑战第9天】本文详尽探讨了Kafka的消息队列架构,包括Broker、Producer、Consumer、Topic和Partition等核心概念,以及消息生产和消费流程。此外,还介绍了Kafka在微服务、实时数据处理、数据管道和数据仓库等场景的应用。针对面试,文章解析了Kafka与传统消息队列的区别、实际项目挑战及解决方案,并展望了Kafka的未来发展趋势。附带Java Producer和Consumer的代码示例,帮助读者巩固技术理解,为面试做好准备。
21 0
|
4月前
|
存储 缓存 弹性计算
Linux网络编程(高并发服务器)
Linux网络编程(高并发服务器)
64 0
|
11月前
|
存储 NoSQL 搜索推荐
闲鱼技术2022年度白皮书-服务端主题-闲鱼如何计算实时优惠:兼顾可扩展、高并发与数据一致性(中)
闲鱼技术2022年度白皮书-服务端主题-闲鱼如何计算实时优惠:兼顾可扩展、高并发与数据一致性
110 0
|
11月前
|
存储 缓存 NoSQL
闲鱼技术2022年度白皮书-服务端主题-闲鱼如何计算实时优惠:兼顾可扩展、高并发与数据一致性(上)
闲鱼技术2022年度白皮书-服务端主题-闲鱼如何计算实时优惠:兼顾可扩展、高并发与数据一致性
162 0
|
11月前
|
存储
闲鱼技术2022年度白皮书-服务端主题-闲鱼如何计算实时优惠:兼顾可扩展、高并发与数据一致性(下)
闲鱼技术2022年度白皮书-服务端主题-闲鱼如何计算实时优惠:兼顾可扩展、高并发与数据一致性
|
存储 消息中间件 编解码
[自己做个游戏服务器二] 游戏服务器的基石-Netty全解析,有例子,多图解释
Netty的大名我想做java 的基本都知道,因为他实在太出名了,现在很多著名的软件都是使用netty作为通讯基础,今天就聊聊Netty,希望能讲清楚,如果懒得看理论,可以直接拉到后面看Hello world。把代码抄下来,运行一下看看。
263 0
[自己做个游戏服务器二] 游戏服务器的基石-Netty全解析,有例子,多图解释
|
XML 移动开发 前端开发
【学习笔记】Web前端到后端数据的交互
【学习笔记】Web前端到后端数据的交互
【学习笔记】Web前端到后端数据的交互
|
Web App开发 安全 网络协议
从客户端的角度来谈谈移动端IM的消息可靠性和送达机制
1、前言 IM App 是我做过 App 类型里复杂度最高的一类,里面可供深究探讨的技术难点非常之多。这篇文章和大家聊下从移动端客户端的角度所关注的IM消息可靠性和送达机制(因为我个人对移动客户端的经验积累的比较丰富嘛)。
3532 0