编辑
在多人游戏世界中,玩家要想获得良好的游戏体验,需要做很多事情——尤其是如果这种良好的体验取决于你的想法。
在线多人游戏,如FPS(第一人称射击游戏)、赛车和一些MMORPG类型的游戏,尤其取决于玩家对游戏反馈的及时有效反应。这个反馈和反应链有很多环节,其中一个环节是你,玩家,另一个环节就是你的“ping”。
还有鼠标/键盘输入延迟、CPU延迟、GPU渲染时间和显示器刷新率等问题,我们稍后会讨论。
目录
那么什么是“Ping”?
如果你看过那些老式的二战潜艇电影,你会想起很多悬疑的场景,船员们蜷缩在黑暗中,听着越来越快的“ping”声。这是一种声纳ping——一种穿过水中并反弹回发射器的声音脉冲,基本上可以确定物体的距离。
编辑
IP地址是您唯一的互联网地址。
信息以小数据包的形式从互联网上的一个地方传到另一个地方,一个接一个。
就互联网而言,ping指的是延迟——数据包从你的电脑或游戏机到互联网上其他地方的另一个IP地址需要多长时间。知道了?
有两种类型的数据包;TCP/IP(传输控制协议/互联网协议)和UDP(用户数据报协议)。
TCP/IP速度较慢,因为要确保数据在应该的位置,并且所有数据都能通过,需要进行大量的来回操作。如果数据包已损坏,将再次要求提供该数据包。
UDP更快;它只是检查以确保数据没有损坏-如果是坏数据,接收计算机就会忽略它。需要发送大量数据以保持游戏更新的游戏使用UDP。
这就引出了丢包
丢包
丢包是你可能经历过的事情;游戏结束了,但是可能网络传输还在这或别的地方在发生。
当UDP数据包没有以良好的状态传输给您时,就会发生这种情况,因此您的控制台/计算机会拒绝它们。
那我们就举个例子,看下Linux系统UDP数据包丢失的情况;
Linux系统UDP丢包的原因有很多,常见的是:UDP消息错误、防火墙策略问题、UDP缓冲区大小不够、系统负载过高等。
这里我们就针对常见的这几种可能性进行分析:
UDP消息错误
如果UDP消息在传输过程中被修改,可能会导致校验和错误或长度错误,Linux将在收到UDP消息时对此进行验证,并在发现错误后丢弃该消息。
如果希望UDP消息校验和及时发送到应用程序,可以使用套接字参数禁用UDP校验和检查:
int disable = 1; setsockopt(sock_fd, SOL_SOCKET, SO_NO_CHECK, (void*)&disable, sizeof(disable)
防火墙策略问题
如果系统防火墙丢包,行为表现通常是所有UDP数据包都没有被正确接收,当然也不排除防火墙只掉线一部分消息的可能性。
如果您遇到非常大的丢弃率,请检查防火墙规则,以确保防火墙不会主动丢弃UDP数据包。
UDP缓冲区大小不足
收到消息后,Linux系统会将消息保存到缓冲区。由于缓冲区的大小是有限的,如果UDP消息太大(超过缓冲区大小或MTU大小),消息的接收速度太快,可能会导致Linux直接丢弃数据包,因为缓存已满。
在系统级别,Linux设置可以为接收缓冲区配置的最大值,可以在以下文件中查看,通常Linux会根据启动时的内存大小设置初始值。
/proc/sys/net/core/rmem_max: 允许设置接收缓冲区的最大值 /proc/sys/net/core/rmem_default: 使用默认接收缓冲区值 /proc/sys/net/core/wmem_max: 允许设置发送缓冲区的最大值 /proc/sys/net/core/wmem_dafault: 使用的默认发送缓冲区最大值
然而,这些初始值并不是用来处理高流量UDP数据包的,如果应用程序接收和发送大量UDP数据包,则需要说这个值更大。您可以使用sysctl命令使其立即生效:
sysctl-w net.core.rem_max=26214400#设置为25M
您还可以修改/etc/sysctl.conf相应的参数,以便在下次启动时保持这些参数的有效性。
如果消息太大,可以在发送方对数据进行分段,以确保每条消息的大小在MTU内。
另一个可以配置的参数是netdev_max_backlog,它表示Linux内核从NIC驱动程序读取消息后可以缓存的消息数量,默认情况下为1000,可以设置为2000等值:
sudo sysctl-w net.core.netdev_max_backlog=2000
系统负载过高
系统CPU、内存、IO负载过高会导致网络中断,例如CPU如果负载过高,系统没有时间进行消息的校验和计算,复制内存等,导致网卡或套接字缓冲区出包,内存负载过高,应用程序处理数据包太慢,IO负载过高,CPU用于响应IO等待,并且没有时间处理高速缓存中的UDP数据包。
Linux系统本身是一个相互连接的系统,一个组件的任何问题都可能影响其他组件的正常运行。这要么是应用程序问题,要么是系统的系统负载不足。对于前者需要及时查找、调试和修复,对于后者也要及时查找和扩展。
利用丢弃数据包
上面提到了系统的UDP缓冲区大小,调整后的SYSCTL参数只是系统允许的最大值,每个应用程序在创建套接字时都需要设置自己的套接字缓冲区大小值。
Linux系统将接收到的消息放入套接字缓冲区,应用程序不断从缓冲区读取消息。因此,有两个与应用程序相关的因素会影响数据包是否被丢弃:套接字缓冲区的大小和应用程序读取消息的速度。
对于第一个问题,您可以在应用程序初始化套接字时设置套接字接收缓冲区的大小,例如以下代码将套接字缓冲区设置为20MB:
uint64_t receive_buf_size=20*1024*1024//2000万 setsockopt(socket_fd,SOL_socket,SO_RCVBUF,&receive_buf_size,sizeof(receive_buf_size));
如果您不是在编写和维护程序,那么甚至不可能修改应用程序代码。许多应用程序都会提供配置参数来调整这个值,请参考相应的官方文件,如果没有可用的配置参数,只能向程序的开发者提及问题。
显然,增加应用程序的接收缓冲区会降低数据包丢失的可能性,但也会导致应用程序使用更多内存,因此要小心。
另一个因素是应用程序读取缓冲区中消息的速度,对于应用程序来说,处理消息应该采用异步的形式
你在哪里丢包了?
要了解Linux系统在执行时会丢弃哪个函数的更多信息,可以使用ropwatchtool,它会监听系统的数据包丢弃情况,并打印出发生数据包丢弃的函数的地址:
# dropwatch -l kas Initalizing kallsyms db dropwatch> start Enabling monitoring... Kernel monitoring activated. Issue Ctrl-C to stop monitoring 1 drops at tcp_v4_do_rcv+cd (0xffffffff81799bad) 10 drops at tcp_v4_rcv+80 (0xffffffff8179a620) 1 drops at sk_stream_kill_queues+57 (0xffffffff81729ca7) 4 drops at unix_release_sock+20e (0xffffffff817dc94e) 1 drops at igmp_rcv+e1 (0xffffffff817b4c41) 1 drops at igmp_rcv+e1 (0xffffffff817b4c41)
有了这些信息,找到相应的内核代码,您就可以知道内核在哪个步骤中丢弃了消息,以及数据包丢失的大致原因。
此外,当网络消息被丢弃时,您可以使用Linux perf工具来列出调用此函数的enkfree_skbfor事件:
sudo perf record -g -a -e skb:kfree_skb sudo perf script
关于perf命令的使用和解释,互联网上有很多文章可以参考。
UDP本身是一种不连接且不可靠的协议,适用于偶尔丢失的消息,不影响程序的状态,如视频、音频、游戏、监控等。对消息可靠性要求较高的应用程序不使用UDP,建议直接使用TCP。当然,应用层也可以重试,以确保可靠性。
如果发现服务器掉线,首先通过监控查看系统负载是否过高,首先尝试降低负载,然后查看丢包问题是否消失
如果系统负载太高,UDP数据包丢失不是一个有效的解决方案。如果应用程序异常导致CPU、内存、IO过高,请定位异常应用程序并及时修复,如果资源不足,监控应该能够发现并迅速扩展
对于大量接收或传输UDP数据包的系统,可以通过调整系统和程序的套接字缓冲区大小来降低数据包丢失的概率。
在处理UDP数据包时,应用程序应该是异步的,并且在两个接收到的数据包之间没有太多的处理逻辑。
为什么我的Ping这么差/这么好?
你的ping是指消息从你的机器到达游戏服务器(或从游戏服务器到你的机器)所花费的时间。
游戏服务器基本上是判断所有连接的玩家在做什么。它知道一切都在哪里,一切都在试图做什么,并且必须决定谁先做了什么——例如,两名玩家向对方发射一连串的子弹。
就服务器而言,重要的响应时间是游戏客户端(在您的计算机或控制台上)接收到您的响应并最终传输到服务器的时间。如果你和你的对手在同一时间开火,但他们的信息比你的早20毫秒到达服务器,bing!胜利属于你的对手。
(当然,这并不总是那么简单——许多系统都允许一定的延迟,但嘿,改天吧。)
服务器还可以让你的游戏客户端(主机或计算机上的游戏程序)了解虚拟世界中发生的事情的最新信息;到处都是战利品,其他玩家开车经过,对他们施法,窗户被打破。你的游戏是在本地渲染的,供你观看,通常会显示你在这个世界上快速移动。
你的游戏接收到的关于世界的数据也比你看到的多得多——服务器将计算这些数据的工作交给游戏客户端。
关于数据传输
你发送到服务器的数据可能会经历一段相当复杂的旅程,这取决于服务器的距离。如果你在自己的机器上运行服务器,这将是1ms的数量级。如果你在巴西比赛,而服务器在冰岛,那么这个信息需要跳几下。总的来说,以下是传输中的步骤:
开始:您的PC/控制台
>到您的路由器/调制解调器
>到您的本地Internet Exchange/节点
>至您的ISP
>收件人。。互联网(这是事情变得复杂的地方)
>到Internet>到其他Internet>(根据需要添加)
>至游戏服务器主机/ISP/数据中心
>至网络交换机
>到游戏服务器
对于从服务器到您的旅程,请颠倒上述步骤。
改进您的Ping
有些事情你可以做,有些事情你无法控制。
您的本地网络
试着用以太网电缆直接插入路由器。如果你在WiFi上付费,而其他人大量使用该频道,你的数据将不得不竞争和排队,这将减慢速度,并可能导致数据包丢失。
您的Internet连接
一个完整的千兆光纤连接在这里是最佳的,但我们还不可能都有。在选择计划时,请记住上传速度是一个重要因素。许多人会通过USB或将手机设为无线“热点”来“捆绑”手机,但要注意的是,一些电话公司会“取消”游戏数据的优先级。
其他滞后因素
最后,别忘了,完整的性能图是这样的,即你可以尽快获得数据,并以最快的速度返回你的响应——也就是说,你可以在屏幕上看到它,并且你的控制器/键盘/鼠标输入可以最快地执行。
使用有线鼠标而不是廉价的无线鼠标。更便宜的无线鼠标使用更旧、更慢的技术与PC通信(不过,一些现代、更昂贵的无线鼠标的响应时间相当长)
CPU密集型游戏需要更好的CPU(更好地确定一切都在哪里)
GPU(图形卡)。你看到的每秒帧数越多,你拥有的数据就越多。但请记住,更好的GPU只能和它输出的显示器一样好——如果你使用的是60hz显示器,你的显卡只需要以每秒60帧的速度渲染。
我们如何测量游戏服务器Ping
眼尖的人可能已经发现,你无法ping UDP连接——它只会朝一个方向发展。那么(例如)Game Server Ping Test - ping checker是如何做到的呢?
嗯,这有点像黑客,但它基本上是有效的。
我们让您的网络浏览器向游戏服务器附近机器上的网址(或者至少在同一数据中心)发送少量请求。这比TCP/IP ping慢大约10%,所以考虑到这一点。。发出砰的声响!
如果你想测试你的游戏服务器在各个地区节点的ping情况,可以使用下面的方式来测试验证Game Server Ping Test - ping checker