zoukankan      html  css  js  c++  java
  • 对 UDP 的一些思考

    先放两个链接

    快速可靠协议-KCP

    可靠 UDP 传输

    最近在玩王者荣耀,发觉两件事:

    1. 可以 4G 和 wifi 无痛切换

    2. 当网络不好的时候,发出去的消息并不保证到达服务器。比如你在很卡的时候做了某些操作,等网络恢复之后你会发现,你还是在某个没有做那些操作之前的状态

    结合这两周阅读的 KCP,我能想到的是,对于第 1 点基于 KCP 就可以实现。

    初读 KCP 的时候,对 conv 变量的存在十分不理解,为什么要用它来表示一个会话,直接由 recvfrom 返回的源 IP 和 port 做 key,找到对应的 ikcpcb 不好么。

    有这个想法是因为脑海中始终还想着 TCP 那一套,也就是 用一个四元组来唯一确定一个连接。直到我后来再次想到上面第 1 个问题,才想明白,在 UDP 之上定义连接的概念,如果还是将它跟四元组绑在一起,那无非是实现了另一个 TCP。而当你用一个 conv 变量来标识一个连接时,这个协议的连接也就天然的跟源 IP 和 port 无关,也就是随便你变换 IP 地址和端口,只要你发来的 conv 是一样的,我就认为你是同一个用户。当然,代价就是你得开始关心 conv 的生成与校验,这又是另一个话题。

    对于第 2 种情况(暂且不论这种做法是否玩家体验最好),却不像 KCP 的行为,因为 KCP 是能保证发出去的数据包一定到达服务器的。

    而云风那篇博客里提到的以请求的方式来保证 UDP 的可靠,貌似恰好可以做到符合王者荣耀的表现。也就是可以做到:1. 允许丢包  2. sn 严格递增

    可问题是 服务器发给客户端的数据是不允许丢失的,这可怎么办。。

    协议层没给的承诺,只好有业务层来做咯~

    首先是帧同步,并且服务器会保存当前这一场的所有帧的数据。那么如果客户端收到了编号为 1,2,5 的数据帧,当收到编号 5 的数据帧时,发现没有收到 3,4 帧,就要向服务端索要丢失的这两帧数据。也就是在客户端的业务层也实现一套请求机制,只不过客户端业务层请求的是数据帧而不是协议层的数据包,服务端对数据帧是没有过期时间的,所以客户端发了请求就一定能求来数据帧!

    还有一个问题,就是在游戏大厅时,服务器发给客户端的消息,也要保证送达,这个怎么办?因为大厅里的消息并非所谓帧同步,理论上服务器也不会保存那些临时消息,所以如果还是基于这种请求模式的话貌似就不太靠谱了。我个人感觉这个时候用 KCP 比较好。当然,场内也可以用 KCP,只不过是另外一种效果。

    总结一下这两种模式:

    1. ack + 超时重传  ->   KCP    可靠     快速重传    但是当网络差到快速重传也发不到的时候,服务器会堆积大量需要重传的数据包

    2.  req  -> rudp   会丢包    但是保证包的顺序     不管网络好坏,服务器发送数据都很平稳

    更新

    修改 KCP 也可以实现王者荣耀的效果。

    ikcp_send 前,先检查 ikcp_waitsnd,如果 waitsnd 大于某个阈值比如 64,则认为当前网络太差,然后不调用 ikcp_send,丢弃这个数据(或者上层消息队列继续缓存这个数据,从王者的表现来看是直接丢弃的)。同时启动一个计时器,如果 waitsnd 持续 10s 都大于 64,则认为网络奇差无比,根本无法游戏,销毁 kcpcb,断线处理。如果 10s 内 waitsnd 一旦小于 32,则认为网络恢复正常,取消掉前面的计时器。

  • 相关阅读:
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    SVN分支
    SVN分支
    SVN 版本回退
    SVN 版本回退
    如何在excel中取消合并单元格后内容自动填充?
    如何在excel中取消合并单元格后内容自动填充?
    如何让自己像打王者荣耀一样发了疯、拼了命的学习?
  • 原文地址:https://www.cnblogs.com/hangj/p/6906781.html
Copyright © 2011-2022 走看看