底下是个专业的文章,你自己看吧。
原文出处:Counter-Strike: CS101: NetGraph
原文作者:Cameron Lloyd
提示:部分内容参照了Jon Mellin之前曾发表在GotFrag的同类文章,但是本文作者除了net_graph之外还会告诉你一些小经验,比如当不知道服务器端maxrates以及确切的cl_cmdrate值时,如何设置ex_interp与cl_updaterate的值。
何谓net_graph?
Net_Graph是Half-Life客户端的特性之一,它能在很大程度上帮助选手了解与据此优化设置以在游戏中表现的更加完美,并且可能也是唯一的途径。Net_Graph的修改途径:打开你的控制台console(~键)接着依次键入net_graph 1,net_graph 2,net_graph 3,这三个参数可以打开与修改你的net_graph设定。
据Steampowered的官方解释是说:Net_Graph是一个能让你查阅网络连接状况的小工具,也可以显示出网络连接,客户端连接,服务器端的连接状况。
net_graph为何重要?
net_graph可以用来检测你当前不合理的网络设置。当然,做为一个重要的工具,net_graph也被一些组织和联赛用来检测与判断截屏是在一场LIVE的比赛里还是在demo中所截。
关于Net_Graph优化的具体细节:
cl_cmdrate(每秒客户端向服务器端传送的数据量)
Mellin曾指出:此数值在理论上等同于服务器的FPS(并非大家所想象的客户端FPS),如果在同一时期内,你的上传速率超过服务器端的计算桢数时,服务器将会产生丢失数据包的现象。将cl_cmdrate值设置的很高虽然也不坏,可它会异常严重的浪费你的通信带宽。
cl_cmdrate是你客户端FPS的因数。验证的方法即:连接至你最喜欢的一个服务器,然后键入net_graph 1。ok,注意你此时的FPS,如果你的cl_cmdrate低于你的FPS值,那么你将注意到红线所标注的地方会产生一条由细小的红点组成的直线。
<IMG onmousewheel="return imgzoom(this);" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open('http://www.pcgames.com.cn/fight/cs/talk/0511/pic/three11_cs101_netgraph_01_thumb.jpg');}" src="http://www.pcgames.com.cn/fight/cs/talk/0511/pic/three11_cs101_netgraph_01_thumb.jpg" onload="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" border=0>
然后,把你的cl_cmdrate略微调高一些,这时再去观察你的FPS,红点也消失了。
<IMG onmousewheel="return imgzoom(this);" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open('http://www.pcgames.com.cn/fight/cs/talk/0511/pic/three11_cs101_netgraph_02_1_thumb.jpg');}" src="http://www.pcgames.com.cn/fight/cs/talk/0511/pic/three11_cs101_netgraph_02_1_thumb.jpg" onload="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" border=0>
Valve如此写道:有时屏幕的最下方会显示亮蓝或者红色的点连接成的直线,这条线显示的是你FPS与cl_cmdrate设定。当客户端把每一桢图像做为数据包成功发送出去的时候,一个亮蓝的标记将会被标示出来。反之,如果数据包被延时传送的话,你将会看见一个红色的标记将会被标示出来。这个时候你就需要调节自己的cl_cmdrate值到你刷新率的一半来观测这几个数值之间的相互影响。
也许Valve已经去掉了亮蓝标记,因为我从来没看见它们出现过。无论如何,一个高的FPS使数据包的传送被延期了,红色的标记意味着cl_cmdrate的值设置过低。
建议:将你的cl_cmdrate设置在略高于FPS的值上,通常情况下两个数值应该相差5。这意味着你将能最大限度的向服务器端传送数据,如果你的连接开始不稳定,并且出现lag情况,那么请将cl_cmdrate值设置的尽可能高,直到lag消失。我们只想尽可能的向服务器端传送更多的数据,实现起来也很简单。另外一个需要注意的地方就是:cl_cmdrate的数值并不需要去强制配合服务器的FPS,因为虽然把最多的数据包传送了出去,可是服务器端并不能接收你发送的全部,接着就会产生可耻的丢包情况。
cl_updaterate与ex_interp(每秒钟客户端向服务器端发送请求的次数 | 两个连续数据包之间隔多长时间插值一次,其单位是秒)
Mellin已经将它们叙述的够详细了,我们的cl_updaterate应该尽量与服务器的sv_maxupdaterate接近,它与cl_cmdrate的工作原理大致相同。我们想要传输最大的数据,而修改这个参数的设定可以达到这一目的。
Valve言及这个网络参数的时候曾提到:cl_updaterate与ex_interp取决于你计算机绘制桢图形的速度,每桢绘制过后,图像在屏幕上被显示出来,并被作为数据包发送出去。可如果你与服务器端的数据传输过低(<10秒)或者丢包过巨,那么客户端就收不到足够的数据包,客户端此时就会启动预测机制,使用预测的不真实的数据来在两个连续的数据包之间插入数值。在这种情况之下,屏幕的下方就会出现一条灰线(位于深蓝色细线的上方),之后鹅黄会变成橘色或者红色,颜色的更改取决于你的数据缺失量。
所以借用Valves提供的信息我们应该可以将cl_updaterate的数值设置正确的,这个值也会自动将ex_interp的值设置为最优(只有当ex_interp 0的时候此数值才会被重设)。
可当我们没有服务器管理权限的时候就无法查看服务器端的FPS,那么又如何知道cl_updaterate被设置在哪个数值的时候是最优呢,其实很简单,连接至一个服务器,再次键入net_graph 1。
<IMG onmousewheel="return imgzoom(this);" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open('http://www.pcgames.com.cn/fight/cs/talk/0511/pic/three11_cs101_netgraph_03_thumb.jpg');}" src="http://www.pcgames.com.cn/fight/cs/talk/0511/pic/three11_cs101_netgraph_03_thumb.jpg" onload="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" border=0>
把我们的cl_updaterate的值设为51,我们将ex_interp的值设置为0,这样做会自动重设我们interp值。但是,请注意下面的图片。我们接到了51个数据包,但是服务器端只发送了30个(假设sv_maxupdaterate 30),此刻屏幕下方显示的是橘色或者黄线,这就意味着客户端额外的插入了一些数据(利用旧的数据插入)。因此产生了丢包,我们自然不希望事情如此下去,所以更改cl_updaterate的值至40,如此一来,我们的ex_interp就会被自动重设
<IMG onmousewheel="return imgzoom(this);" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open('http://www.pcgames.com.cn/fight/cs/talk/0511/pic/three11_cs101_netgraph_04_1_thumb.jpg');}" src="http://www.pcgames.com.cn/fight/cs/talk/0511/pic/three11_cs101_netgraph_04_1_thumb.jpg" onload="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" border=0>
可排成一条直线的黄点只是减少了而并没有消失,可见丢包情况依然存在,原因就在于我们只能从服务器端接收到30个数据包,这也会把我们的interp数值设错。所以我们将cl_updaterate值修改到30,interp随之重设,ok,搞定。
<IMG onmousewheel="return imgzoom(this);" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open('http://www.pcgames.com.cn/fight/cs/talk/0511/pic/three11_cs101_netgraph_05_thumb.jpg');}" src="http://www.pcgames.com.cn/fight/cs/talk/0511/pic/three11_cs101_netgraph_05_thumb.jpg" onload="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new window\nCTRL+Mouse wheel to zoom in/out';}" border=0>
我们想接收来自服务器端的所有数据,不遗失任何一个包,所以请大家把ex_interp的值设置恰当,利用上文所述的方法也不失为妙计之一。
如此一来,客户端cl_updaterate的值就会与服务器端的sv_maxupdaterate相配,这样借助真实的实时的数据,客户端就可以绘制出选手真实所在的位置以及移动,并且不会丢包。
rate(限制客户端每秒向服务器端传输数据的量)
Well,我们想做的一切就是逐渐的增加这个数据,直到在枪战中没有choke产生。这也可以保证客户端能够顺利发送与接收数据,否则我们的ex_interp也会出现错误。
cl_smoothtime
Valve对此的解释为:预测误差的更正在画面上表现的非常明显,你的视角将会变的很卡,那是因为预测误差的错误过一小段时间就会被修正。
个人看法:我将其数值设置为0,可是我们想让客户端插入的是真实数据,在那种画面看起来比较连贯的情况下,我们接收到的,确切的说是在屏幕上绘制出来的图像却不是真实的。所以,假如我们把cl_smoothtime设置为0的时候,客户端的插入数据就不会平滑画面,也不会修正预测误差,此时我们就可以看到选手所在的真实位置。不过请注意,这样的设置也许会使你的画面在选手移动的时候看起来很卡,但是他们所在的位置却是没有被客户端的预测机制修改过的,真实的位置!
当然,正式比赛的时候选手独立修改这些参数也许并不会被允许,况且组委会或许已经把所有的参数都调节至完美地步了,可你自己在网络上面横行的时候却可以用用。希望本文能给大家带来些帮助,看不懂也没有关系,也请继续关注此系列的其他文章,精彩的都在后头呢。另外一件比较羞耻的事情就是:因为这篇文章的技术性太强,原文作者的表述也有些小问题,所以也许文中会有错漏之处,希望大家能够留言指正,小编同志将无以回报,决定以身相许来着。本文到此结束。
参考文献:
Jon Mellin, CS Netcode Explained, 2004
Valves document on netgraph, available in Half-Life SDK.
Valves关于netgraph方面的文档,在Half-Life 的SDK中可以查阅到。
Valves document on source's network traffic.
Valves关于Source在网络阻塞方面的文档。
*提示*Valves关于Source的文档只用于cl_smoothtime,它的工作原理与1.6版的CS毫无二致,其他所有信息皆适用于1.6版。
附CS1.6网络参数解析:
本文将深入探讨一些CS中有争议的关于网络的参数。网络参数是一个相对新的课题,那些顶尖的选手也是从1.3时代欧洲与美洲的激烈碰撞中才开始注意到的。在1.5的时代,选手们开始认真研究特定网络参数的意义。事实上,大多数人直接采用了别人的正确设置。尽管如此,到了1.6,Valve修正了代码中的一个错误,反而造成了更多的混乱。原来正确的设置由于Valve的反作弊程序(VAC)而不能发挥其效力。你们中的有些人可能由于我很久之前的那篇“ex_参数解析”的文章而记得我。
这个观点是通过两年来试验和观察累计而成的。近来有些事情使我提起了对网络参数的兴趣:网管强迫玩家使用错误的参数,局域网赛事中选手由于使用正确的参数而被取消资格等等。最近我通过和一位Valve员工之间的一系列通信而确认了本文中的大部分内容。(对于你们关于demo问题的那些疑问,Valve确实在研究解决方案。)要声明的是,本文所含内容不会使你成为另外一个“Spawn”,但是可以消除错误的对他人关于网络参数的指责并提供一个更加平衡的竞技环境。
下面,我将对我认为重要的网络参数给出一个概述并介绍一下其背景。然后我会给出网络参数建议值,并解释为何如此建议。
请注意:
以“sv_”或者“sys_”开头的参数是服务器端参数,如需修改必须用远程控制命令“rcon”修改。直接修改该参数将导致本地机器的参数被修改,而不是服务器上的参数。
“ex_interp”和“cl_updaterate”两个参数之间的关系极端重要,阅读下文关于其中任何一个的时候,也请阅读关于另外一个的部分。
本文阅读对象主要是那些用宽带上网的读者。
一般信息:
cl_cmdrate:
这个参数决定了每秒钟你--即客户端发给服务器多少个数据包。很显然,这个值越高,服务器对你执行的命令的响应就越快。如果你拥有宽带网并且是其唯一使用者,把此值设高对你没什么坏处。如果你和你的朋友在一处上网打CS,并且能感觉到经常出现延迟的现象,那么这个命令就是罪魁祸首。大多数的宽带(主要是ADSL)并不提供足够的上传带宽,而这恰恰是“cl_cmdrate”所需要的。
cl_updaterate:
“cl_updaterate”和“cl_cmdrate”颇为类似,只是反其道而行之。它控制的是每秒钟你从服务器端接收的数据包的数量。因此,它依赖的是你的下载速度。你的“cl_updaterate”值越高,你和服务器的同步率就越高。既然只有服务器能决定你是否打中了,你当然希望收到足够多的数据包以保持和服务器同步。
sv_maxupdaterate:
如同“cl_updaterate”控制每秒钟客户端发给服务器端的最大数据包数量,“sv_maxupdaterate”就是每秒钟服务器端允许客户端接收的最大数据包数量。因此,把“cl_updaterate”设置的高于“sv_maxupdaterate”是毫无意义的。
sys_ticrate:
这个参数设定的是每秒钟服务器将计算出的帧数。默认值是100。为什么服务器的FPS(每秒钟的帧数)重要呢?这个参数本身决定了你在这个服务器上的感觉。我肯定我们都有过这种经验:有些服务器好像是架设在“深蓝”(或者曙光?龙芯?呵呵)上,而我们就好像是在局域网里打比赛一样。
“sys_ticrate”只是设定你服务器的最大FPS。一般来说,你的服务器不会达到这个值,因为你的操作系统并不允许你这样。有很多种不同的方法来提升服务器的FPS,但是其中很多种都需要服务器提供商的合作。请记住,提高服务器的FPS会导致服务器提供商的机器CPU加重负担,因此多半服务器供应商们不会这么做。(出于某种原因,在de_inferno和de_aztec上提高服务器的FPS会导致CPU过载)。基于Windows的“半条命”服务器的默认FPS是64,而基于Linux的服务器的默认FPS是50。某些情况下,你可以把服务器FPS提高到512。是否使用如此之高的服务器FPS现在还有争议,但是就我个人的经验,通常在200FPS下你的游戏感觉会有明显的改善。
稳定性是关键。FPS在100和512之间跳来跳去只会使你的游戏感觉更糟糕,因此当你的服务器一般状态下是150FPS的时候,不妨把“sys_ticrate”设成150。
如果你有服务器的远程控制权限并且想知道服务器当前的FPS,那么就在命令台中输入“rcon stats”。要检查你的服务器有没有被提升过,暂时把“sys_ticrate”设成10000,并输入“rcon stats”。如果你的服务器FPS大于100,那么你的服务器就是被提升过了。
ex_interp:
开始之前,韦氏大辞典如下定义“interpolate”(插值):
Main Entry: in·ter·po·late (主要词条: interpolate)
3:to estimate values of (a function) between two known values (3:估计两个已知函数值中间的函数值)
intransitive senses : to make insertions (as of estimated values) (不及物动词: 插入(在估计值的时候))
你不可能完全和服务器同步,因为你只是每秒钟接收到一定量的数据包。比如:图所示。随着数据点的增加,插值图形将越来越接近原本的圆。CS中我们可以认为这个圆就是一个玩家中在一秒钟不同的位置。从服务器的观点来看,它就是一个完美的圆,而客户端不得不通过插值来预测两个数据包中间的空档。
这就是“ex_interp”出现的原因。两个数据包之间的空档,就要由“半条命”的预测机制来决定了。“ex_interp”设置的是在两个连续数据包之间隔多长时间插值一次,其单位是秒。如上图所示,这些小的时间段就对应了插值多边形的边。因为插值是由客户器端做出的,他和服务器端的判断并不是完全一样。没什么东西能替代真正的数据包,但是插值预测大多数情况下都做得不错。
对于在线游戏的推荐值:
rate:
我已经确认过rate最高是20000,设成20000以上是没有任何意义的,甚至有可能会降低性能。
推荐值:
rate 20000
sv_maxrate:
这个值通常会被设成0。对于在线游戏来说,这并不是最优值。“sv_maxrate 0”会自动监测所有玩家的连接速度,并满足每个人的要求。假定“半条命”允许玩家使用超过20000的“rate”值,如果一个玩家疯到把“rate”设成999999999,服务器会满足他的要求。这不仅导致了带宽的浪费,也导致了服务器过载。因此我推荐一个更安全的值“20000”。事实上,“sv_maxrate 0”和“sv_maxrate 20000”有可能效果是相同的,但是预防措施总是没有坏处的。
推荐值:
sv_maxrate 20000
cl_cmdrate:
这个参数的理想值应该是和服务器的FPS一样(而不是原来大家认为的客户端FPS)。如果你向服务器端发出的更新超过服务器本身的FPS,通常那些多余的数据包就会被丢弃掉。因此,“cl_cmdrate”设置过高没有什么大坏处,但是它浪费了你的带宽。
推荐值:
cl_cmdrate 等于或者大于服务器FPS
ex_interp:
把这个值设成0。CS会自动把你的“ex_interp”设成“1/cl_updaterate”(你的命令台会告诉你“ex_interp”被强制设成XX毫秒。原文“ex_interp forced up to xx msec”)。这是因为两个数据包之间的时间间隔就正好是1/(每秒更新次数),这就是你需要客户端做出插值预测的时间长度。调整“cl_updaterate”会自动调整“ex_interp”(当“ex_interp”设成0的时候)。我建议你只修改“cl_updaterate”,而让你的CS来自动修改“ex_interp”。你现在不能把“ex_interp”设置的低于“1/cl_updaterate”,而把它设高则导致了你射击对手的时候不得不瞄准出现在你屏幕上的人的后方,这种行为通常被认为是作弊(原文exploit,因为欧美比赛中exploit也算是作弊的一种,因此这里就直接翻译成作弊了)。比如,如果你的“cl_updaterate”是101,你“ex_interp”的正确值就是“1/101=0.009”(9毫秒)。而使用默认值0.1就形成了前述的“作弊”(又是exploit,我ft)
推荐值:
ex_interp 0
cl_updaterate:
很长时间以来的做法是让“cl_updaterate”从101开始下降,降到你可以接受的“choke”值。可以用命令“net_graph 3”来查看“choke”。对我来讲,“choke”是我最后才关心的一个数值。事实上得到“cl_updaterate”的最优值是更为复杂的。CAL比赛服务器端设置都是“sv_maxupdaterate 101”,所有有人可能会觉得“cl_updaterate”应该设成101。理想状态下,这是对的,但现实中这并不正确。美国大部分的服务器并不能提供100FPS,这就意味着每秒钟服务器不可能发出100次更新。因此“cl_updaterate 101”除了让你的“ex_interp”变成0.009之外,并不能保证你每秒钟都收到100次更新,这就导致了玩家们的游戏感觉不断在变。既然没有(除非有远程控制权,“rcon stats”)知道服务器FPS的方法,我们就不得不猜测“cl_updaterate”的最优值。你可能说:“不妨把“cl_updaterate”设成101,这样就保证了能尽可能多的接收到数据包”。这样做的问题是忽视了“cl_updaterate”对“ex_interp”的影响,而实际上你的“ex_interp”应该设的更高。
为了找出最优的“cl_updaterate”值(记得把“ex_interp”设成0),将其值从101开始下降直到游戏中的人物只有非常轻微的抖动。“轻微的抖动”的程度只是个人的偏好而已,只要你的“ex_interp”等于“1/cl_updaterate”,游戏中的人物就应该是在正确的位置上。你必须针对每个服务器来调整你的“cl_updaterate”。别害怕使用低于50的“cl_updaterate”值。预测机制会发挥它的作用。注意:大多数公众服务器会把“sv_maxupdaterate”设成30,这时“cl_updaterate 30”就是最正确的。
请注意“cl_updaterate”从低向高调整是行不通的。一旦你的“cl_updaterate”设置到了一个较高的值,“ex_interp”并不会自动调整,而你不得不一次又一次的手动输入“ex_interp 0”。下面是我写的一个调整“cl_updaterate”的很方便的脚本:
调整更新速度的设置文件
推荐值:
“cl_updaterate”应该等于服务器的FPS,而且不应该超过服务器的 “sv_maxupdaterate”值。
sys_ticrate:
寻找合适的“sys_ticrate”值需要做一些试验。首先,如果你的服务器fps没有被提高到100以上,那么把这个值设成大于100是毫无意义的。如果你碰巧租到的是一个高性能服务器(即FPS被提升过),那么你就可以对“sys_ticrate”做点什么了。尽管越高的FPS是件好事,但是把“sys_ticrate”设置的超过200通常不是件好事。比如你把“sys_ticrate”设成9999, 你的服务器FPS则会随着当前地图上的战况而在150到1000之间晃悠。因此把它设置的低于200,会提供一个更稳定的游戏环境。通常,服务其提供商的每台计算机都会运行多个“半条命”服务器,所以如果所有这些服务器的“sys_ticrate”很高的话,就会占用极大的CPU资源。而使得每个“半条命”服务器上的玩家都感觉不爽。(并且多半你的服务器供应商还会增加月租金)。
最后,服务器的FPS只能是某些特定的数。比如,我的服务器只能工作在85、102、128、170、256等几个FPS下,而且不会出现其它的FPS值。如果你把“sys_ticrate”设成100,你的服务器会自动选取小于100的那个工作值(上面情况下,将是85)。所以请试着在你想要的FPS上加上20到50,来设置“sys_ticrate”。
推荐值:
sys_ticrate 110-180, 取决于你服务器的质量。
局域网赛事注意事项:
那些局域网赛事的主办者,比如CPL,使用“cl_updaterate 101”的原因是由于他们使用了高品质的服务器。如果服务器的FPS被提高到100以上,那么使用“cl_updaterate 101”就是一个合理的值。一个快速的查看你局域网服务器FPS是否被提高的方法是看玩家的ping。一个运行在50或者64FPS的默认服务器通常会让玩家的ping超过15毫秒,而一个被提升的服务器则会提供一个远小于此的ping值,通常是在5毫秒左右。就我所知,CPL、ESWC和WCG都是使用的提升过的服务器。 |