首页 > 其他分享 >游戏服务器架构:使用KCP 加速游戏消息,让全球玩家流畅联网

游戏服务器架构:使用KCP 加速游戏消息,让全球玩家流畅联网

时间:2022-11-01 14:40:22浏览次数:118  
标签:窗口 重传 发送 KCP kcp 服务器 接收 拥塞 游戏

定义

           kcp协议是传输层的一个具有可靠性的传输层ARQ协议。

          它的设计是为了解决在网络拥堵情况下tcp协议的网络速度慢的问题。

           kcp力求在保证可靠性的情况下提高传输速度。

          kcp协议的关注点主要在控制数据的可靠性和提高传输速度上面,因此kcp没有规定下层传输协议,一般用udp作为下层传输协议,kcp层协议的数据包在udp数据报文的基础上增加控制头。当用户数据很大,大于一个udp包能承担的范围时(大于mss),kcp会将用户数据分片存储在多个kcp包中。因此每个kcp包称为一个分片。

KCP重传机制

         为了提供可靠性,kcp采用了重传机制。

        为实现重传机制,kcp为每个分片分配一个唯一标识,接收方收到一个包后告知发送方接到的包的序号,发送方接到确认后再继续发送。而如果发送方在一定时间内(超时重传时间)没有接到确认,就说明数据包丢失了,发送方需要重传丢失的数据包,所以发送方会把待确认的数据缓存起来,方便重传。  停等的重传机制发送一个包后必须等待确认后再发下一个包,传输速度较慢,所以为了提高发送速度,发送方可以不必再每发送一个包后就进行等待确认,而是可以发送多个包出去,然后等待接收方一一确认。又由于接收方不可能同时处理无限多的数据,因此需要限制发送方往网络中发送的数据数量。因此接收方限制发送方在未收到确认之前只能发送wnd大小的数据,这个机制叫做滑动窗口机制。

        kcp采用滑动窗口机制来提高发送速度。由于UDP在网络中的传输是不可靠的,因此会出现丢包和包的乱序。kcp是可靠的保证数据有序的协议,所以为了纠正包的乱序。接收方维护一个接收窗口。接收窗口有一个起始序号rcv_nxt以及尾序号rcv_nxt+rcv_wnd。如果接收窗口收到序号为rcv_nxt的分片那么rcv_nxt就加一,形象一点的说法是滑动窗口右移,并把该数据放入接收队列供应用层取用。如果收到的数据在窗口范围内但不是rcv_nxt那么就把数据保存起来,等收到rcv_nxt序号的分片时再一并放入接收队列供应用层取用。

丢包问题

        当网络拥堵严重时,会发生丢包,丢包发生时kcp为了保证可靠性需要重传数据。而发送方需要判断什么时候发生了丢包,以及丢了哪些包。

        为了解决这个问题,发送方为缓存队列中的每个包设置了包序号和超时重传时间。当检测到当前时间超过了分片的超时重传时间,该分片还没有得到确认时就会触发该分片的超时重传。  
        数据在网络中的传输时间是不固定的,因此超时重传时间比较长。而为了尽早地判断出数据包的丢失,kcp引入了快速重传机制。快速重传机制工作原理是,当发送方发送了n,n+1,n+2...等等包出去后,接收方没有接收到n,而接收到n+1,n+2..等等n号包之后的包,这时因为n号包之后的包都已经接收到了,而n号包还没有接收到,所以可以认为n号包已经丢失了,告知发送方可以进行快速重传。kcp为了支持快速重传,接收方需要告诉发送方,哪些包已经成功收到了,哪些包没有收到。因此接收方返回发送方的确认数据(ack)中包含以下信息:接收窗口左端的序号rcv_nxt,接收到的大于rcv_nxt的包序号sn。rcv_nxt的含义是接收方已经成功按顺序接收了rcv_nxt序号之前的所有包,大于rcv_nxt的序号sn表示的是在接收窗口内的不连续的包。发送方接收到接收方发过来的数据时,首先解析rcv_nxt,把发送缓存中所有小于rcv_nxt序号的包全部移除掉(因为这些包全都都已经正确接收了)。然后再解析sn,遍历发送缓存,找到所有序号小于sn的包,这些包就是可能在网络中已经丢掉了的包,只是可能,因为有可能这些包只是拥堵在了网络中,需要更长的时间到达,所以这里我们设置一个快速重传的门限,对每个分片维护一个快速重传的计数,每收到一个ack解析sn后找到了一个分片,就把该分片的快速重传的计数加一,如果该计数达到了快速重传门限,那么就认为该分片已经丢失,可以触发快速重传,该门限值在kcp中可以设置,tcp中是3。  

        丢包发生时,由于滑动窗口的存在,假设第n个包丢失了,但是此时n+1,n+2号包却已经传输成功了,此时最好只重传丢失的n号包,而不重传成功传输的n+1,n+2号包,这个机制叫做选择重传,选择重传的关键在于接收方要告知发送方哪些包已经收到了,哪些包没有收到,为了最小化数据量,接收方可以告诉发送方哪些包已经按序收到了,哪些包是收到的但是不连续。所以返回的ack中包含rcv_nxt和sn。rcv_nxt代表收到的所有连续的包,sn代表哪些不连续的包收到了,那么根据这两个参数可以计算出来没有收到的包的序号。  

        当网络实在很拥堵的时候(一般由于网络消息太多,堵车了),kcp会限制发送方发送的数据量,这叫做拥塞控制,拥塞控制就是告诉发送方,网络太堵了,应该少发一些数据,因此在滑动窗口的机制上引入了拥塞窗口,也就是说发送发发送的数据不得超过拥塞窗口,拥塞窗口的大小会随网络情况而变快,网络快拥塞窗口就大,反之同理。

拥塞窗口

        那么拥塞窗口应该等于多少呢?

        解决这一问题的原则是,让网络充分被利用,但是不能堵塞,这里引入了慢启动机制,慢启动也就是控制拥塞窗口从0开始增长,随着数据不断地成功传输,拥塞窗口逐渐增大,直至达到饱和,也就是网络的收发平衡。

        为了快速达到网络的收发平衡,拥塞窗口采用倍数增长。也就是每成功发送一个数据拥塞窗口加一。

        举个例子,窗口大小为1时,发送一个数据,成功后窗口变成2,之后发送两个数据出去,成功接收后窗口大小变为4。为了方便让更多的用户连入网络时,网络能有足够的流量提供给用户,还可以设置拥塞门限,拥塞门限值就是当用户拥塞窗口快速增长到门限值后就减慢增加速度,缓慢增长,腾出流量给其它用户。  

        但是当网络很拥堵的情况下,导致发送数据出现重传时,这时说明网络中消息太多了,用户应该减少发送的数据,也就是拥塞窗口应该减小。怎么减小呢,在快速重传的情况下,有包丢失了但是有后续的包收到了,说明网络还是通的,这时采取拥塞窗口的退半避让,拥塞窗口减半,拥塞门限减半。减小网络流量,缓解拥堵。当出现超时重传的时候,说明网络很可能死掉了,因为超时重传会出现,原因是有包丢失了,并且该包之后的包也没有收到,这很有可能是网络死了,这时候,拥塞窗口直接变为1,不再发送新的数据,直到丢失的包传输成功。

在上述原理之下,kcp为了提高传输速度,还可以有许多选项供用户选择:

  • kcp的拥塞控制可以取消
  • ack回复可以设置成无延迟ack回复
  • kcp的快速重传门限可以控制

  



标签:窗口,重传,发送,KCP,kcp,服务器,接收,拥塞,游戏
From: https://blog.51cto.com/u_14934686/5813588

相关文章

  • node04_05时钟web服务器
    1.创建clock文件夹,里面有index.hrml和对应的css文件  2.编写node代码//1.1导入http模块consthttp=require('http')//1.2导入fs模块constfs=require('fs')......
  • node4_01创建基本的web服务器
    //1.导入http模块consthttp=require("http")//2.创建web服务器实例constserver=http.createServer()//3.为服务器实例绑定request实例,监听客户端的请求server.......
  • 使用Docker一键搭建FastDFS+Nginx分布式文件服务器
    做过很多项目在图片上传上一直使用的是FastDFS,刚开始得知搭建一个这样的系统非常复杂,所以直接使用了淘淘商城的虚拟机。在后面的项目中,最终选择在在阿里云上自己搭建一个Fas......
  • apache网站服务器配置与优化
    Apache部署超详细教程Dribblelife于2019-05-2323:14:53发布39190收藏381分类专栏:linux版权linux专栏收录该内容42篇文章6订阅订阅专栏Apache服务器部署背景Apa......
  • unity3d:最简单的服务器,把收到消息发回客户端
    usingUnityEngine;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.Net.Sockets;usingSystem.Net;usingSystem.Threading;usingSystem;usin......
  • web服务器9express.static
    constexpress=require('express')constapp=express()//调用static函数托管静态资源可托管多个//从上往下查找//做伪装app.use(express.static('./index')......
  • 第三十三章 使用 CSP 进行基于标签的开发 - 使用Hyperevents #server和#call调用服务
    第三十三章使用CSP进行基于标签的开发-使用Hyperevents#server和#call调用服务器端方法使用Hyperevents#server和#call调用服务器端方法hyperevent是我们对web浏......
  • HCIE-服务器虚拟化运营One
    服务器虚拟化特性集群特性资源在线调整在线调整CPU/内存添加/删除网卡添加/删除磁盘内存复用开启之前分配多少占用多少,开启之后使用多少分配多少内存共享......
  • HCIE-服务器虚拟化运营Two
    服务器虚拟化资源计算资源虚拟CPU&虚拟内存虚拟化计算资源池虚拟化层主机存储资源存储资源真实的外接存储设备类型IPSANNAS存储设备外......
  • HCIE-服务器虚拟化运营Three
    虚拟机创建流程明确创建方式新建虚拟机导入虚拟机克隆虚拟机模板部署虚拟机模板转为虚拟机准备资源计算存储网络镜像模板(模板创建虚拟机)具体步骤......