有网络丢包,电子秤按键部分失灵怎么修偶尔失灵的情况吗

为何我家笔记本无线网卡的网时段时续,有事得等他重新连接上,才能再用,什么情况啊
按时间排序
建议从以下方面去检测一下: 1、运营商进线直连电脑,单机上网,然后ping 运营商服务器。如 有丢包,请打运营商服务热线。自已没法解觉。 2.请将电脑杀一下毒后,在把无线网卡初初始化一下。很可能是中毒引起的 3.如果都没问题了,那可以考虑,换个无线路由器试试,之前我也碰到过一差的路由器也有此类的问题! 希望能对你有帮助!Gatsby_XTS6!
设置下你的网络属性吧,家庭or办公or公共。建议买专业的无限路由器,不要图方便使用电信或联通带的猫无线路由。
如果需要连接别的无线网络 要有两个条件: 1:你搜索范围内有无线发射器 2:要知道别人的无线发射器的上网密匙(即密码)
时断时续这个比较复杂,可以这样分析:1、如果用无线连接,不管手机还是电脑,都要考虑信号强弱问题?附近是否有同一波段无线信号干扰问题?改用有线若马上能连接,则断定是这个问题。可尝试改另外一个信号波段。修改无线密码和加密,附止被蹭。2、如果有用线连接也是时断时续,一般为路由器接入用户过多,导致路由器处理不过来,掉包率大增,路由器甚至会死机。3、用360体检后马上可以,没办法,这很大可能是木马或病毒问题了,为了根本确实是否病毒问题,有条件可换台电脑进行测试,无条件最好的办法就是重装系统。因为你都用360体检过,杀毒肯定是起不到很好作用的。(以上为回复其它问题复制过来,可作参考)感叹号作用就是代表网络异常,可以尝试设置固定IP地址。
如果你不是路由器就还要波号,是路由器就是你网络有问题。打客服吧!
ip配置一下
感谢您为社区的和谐贡献力量请选择举报类型
经过核实后将会做出处理感谢您为社区和谐做出贡献
确定要取消此次报名,退出该活动?
请输入私信内容:德意龙键盘上哪个是静音键
按时间排序
笔记本键盘出现了按键失灵情况,这种情况多是由于软件原因或键盘串键、短路或其他硬件故障等原因造成的,导致其他按键失灵,建议您可以做如下检查确认故障进行尝试:1.开机出现SAMSUNG 图标时按F2键进入BIOS设置,按F9键将BIOS恢复为出厂模式,按F10保存并重启。2.用U盘或光盘启动进入PE或Dos模式中确认是否可用。3.开机出现系统图标前快速按F8键进入安全模式后进行尝试,确认是否为系统或软件故障引起。4.查看按键下是否有异物,如有异物建议您将机器倒置或摇晃,也可请使用毛刷,、镊子、气吹等工具进行简单的清除(注意不要损坏按键下支架,不建议非专业人员尝试,以避免更严重的损坏)。若情况严重建议您送至售后服务中心由专业工程师进行清洁维修。5.确认键盘是否曾有浸液史、确认失灵按键按下后是否可正常弹起,若发生过浸液或不能正常弹起则需要到售后服务中心,由工程师帮助您进一步检查与维修。6.重新安装操作系统尝试(提示您先备份重要数据与资料)。7.若您需临时使用,也可连接USB键盘使用。
开关一般在键盘的背面或者侧面,有on和off标记的
可能是键盘按键冲突网速跟不上,有网络卡顿的现象键盘失灵,按键的时候并没有传感到电脑键盘的主板坏了按键出现堵塞的现象,导致你按键没达到预期效果。
根据你的描述推断应该键盘问题,因为键盘不兼容,所以有时会出现你上述说的情况,可以换一个其他键盘试一下,如果不再发生说明是键盘问题,下载一个驱动精灵自检一下然后下载一下它所需的驱动就好了。
这个键盘不是机械键盘,只是个薄膜键盘,有可能是FN加上Pause Break键,FN是原来的右win键,Pause Break带个小灯的标志,是右侧NumLock绿灯左侧的那个键。
在右看看输入法图标关键属性不被设置在这里你设置 - 其他窢梗促妓讵幻存潍担璃快捷键SHIFT + CTRL键无法使用,那么你可以尝试使用SHIFT + ALT 可能是你CTFMON.EXE过程删除;或者你干脆不要让他变成自动启动。
有配一个像U盘样的插USB驱动一下
出现走走停停的情况,一般是这2种情况:1,网络问题,丢包率高,高延迟,就会想幻灯片一样,一顿一顿的2,键盘的摁键,接触不良,如果是键盘问题,你可以这样试一下,1,常摁W,A,D,S 空格件,看cf人物移动情况2,在网页上,切到输入法,常摁W,A,D,S 空格件,看是否顺畅,排除键盘问题如果是网络问题,有线网连接,这个只能建议你打电话投诉/保修,或者换一家了无线网出现延迟的话,可以将无线路由器离墙面远一点,周围空旷一些,可以让信号好一点,或者离你的电脑近一些,再或者买一个大功率的路由器(什么穿墙王路由器)
感谢您为社区的和谐贡献力量请选择举报类型
经过核实后将会做出处理感谢您为社区和谐做出贡献
确定要取消此次报名,退出该活动?
请输入私信内容:&p&这是通信领域的话题了,低延迟传输有上百种优化方式,上面说的那些冗余码只是很小一部分,不考虑信道容量的冗余编码系统都是在耍流氓,不用等到同信道内跑两套这样的协议你才会发现问题,一套协议再接近信道带宽容量限制时,就会出现指数上升的丢包率,所以不考虑带宽检测的冗余法就是一个残次品。&/p&&p&要系统的解决低延迟传输问题,需要同时在传输层,协议层,路由层,应用层几个方面着手:&/p&&p&&br&&/p&&p&&b&传输层带外冗余:弱智重复法&/b&&/p&&p&设你要发送的数据为 x1-xn,你实际发送出去的包为 p1-pn,那么比如 Pn = [Xn, Xn-1, Xn-2],重复前面出现过的 1-2个数据,丢包了你可以随时恢复出来。&/p&&p&&br&&/p&&p&&b&传输层带外冗余:异或法&/b&&/p&&p&每发四个包 x1-x4,你多发一个冗余包,内容为前面四个包的异或: R = x1 ^ x2 ^ x3 ^ x4,那么本组数据五个数据包(x1-x4, R)中任意丢失一个,都可以从其他四个异或得到。当然,不一定要四个包冗余一个,你可以根据情况和丢包率,两个包或者三个包冗余一个。&/p&&p&&br&&/p&&p&&b&传输层带外冗余:解方程法&/b&&/p&&p&把每个数据包看成一个整数,要发送 x1-x4 四个包,并不直接发送x,而是将他们进行线性运算得到 y1-y7,然后发送出去:&/p&&div class=&highlight&&&pre&&code class=&language-text&&A1 * x1 + B1 * x2 + C1 * x3 + D1 * x4 = y1
A2 * x1 + B2 * x2 + C2 * x3 + D2 * x4 = y2
A3 * x1 + B3 * x2 + C3 * x3 + D3 * x4 = y3
A4 * x1 + B4 * x2 + C4 * x3 + D4 * x4 = y4
A5 * x1 + B5 * x2 + C5 * x3 + D5 * x4 = y5
A6 * x1 + B6 * x2 + C6 * x3 + D6 * x4 = y6
A7 * x1 + B7 * x2 + C7 * x3 + D7 * x4 = y7
&/code&&/pre&&/div&&p&接收方收到一组数据以后,发现y3, y5, y7丢失,得到:&/p&&div class=&highlight&&&pre&&code class=&language-text&&A1 * x1 + B1 * x2 + C1 * x3 + D1 * x4 = y1
A2 * x1 + B2 * x2 + C2 * x3 + D2 * x4 = y2
A4 * x1 + B4 * x2 + C4 * x3 + D4 * x4 = y4
A6 * x1 + B6 * x2 + C6 * x3 + D6 * x4 = y6
&/code&&/pre&&/div&&p&如果y1-y7在发送的过程中丢失了三个:y3, y5, y7 观察等式。变量任然有4个,参数也任然有四个A1, A2, A4, A6, B?, C?, D? 四个变量,四个等式,那么我们可以通过解方程求出x1-x4,这就是一个矩阵运算和求逆的过程,也就是楼上说的 Read-Solomon 冗余码的基本原理(PS: shorthair/long hair两个库写的很烂呀),实际传输时需要根据网络质量来选择每组数据和冗余包的比例。&/p&&p&&br&&/p&&p&&b&传输层网络评估&/b&&/p&&p&需要一套比较强大的系统,实时评估当前网络质量(RTT, 丢包率,抖动值,可用带宽),为协议决策提供参考,比如这时一个带宽很大,延迟却很高的信道呢?还是带宽很小,延迟也很小的信道呢?不同的情况对应不同的策略,当前丢包是常规丢包?震荡性丢包?还是接近信道限制出现无可挽回的丢包?再根据当前协议出于什么情况?交互模式还是单向传输模式,来给出最佳的传输策略。不考虑这些情况的协议,都是比较弱智的(比如楼上提到的几种)。&/p&&p&&br&&/p&&p&&b&协议层决策模型&/b&&/p&&p&根据不同的情况,来推导不同的数据包丢失后,对整体协议的影响,从而通过马科夫决策过程,来找到哪个包丢失的代价最大,以此来指导冗余包的生成过程:&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-b41ebaea6c5c07a2b21a3e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&440& data-rawheight=&362& class=&origin_image zh-lightbox-thumb& width=&440& data-original=&https://pic4.zhimg.com/50/v2-b41ebaea6c5c07a2b21a3e_r.jpg&&&/figure&&p&并且根据网络统计,实时修正决策参数。&/p&&p&&br&&/p&&p&&b&协议层响应模型&/b&&/p&&p&对 TCP 协议而言,是一个中庸的协议,协议质量的几个要素:公平性,延迟性,带宽利用率。三者不可得兼,然而可以根据你应用情况进行适当调整,牺牲部分公平性和降低部分带宽利用率换取低延迟,比如:&/p&&ul&&li&RTO翻倍vs不翻倍:TCP超时计算是RTOx2,这样连续丢三次包就变成RTOx8了,十分恐怖,而如果不x2,只是x1.5(实验证明1.5这个值相对比较好),可以很好提高传输速度。&/li&&li&选择性重传 vs 全部重传:TCP丢包时会全部重传从丢的那个包开始以后的数据,我们可以用选择性重传,只重传真正丢失的数据包。&/li&&li&快速重传:发送端发送了1,2,3,4,5几个包,然后收到远端的ACK: 1, 3, 4, 5,当收到ACK3时,我们知道2被跳过1次,收到ACK4时,知道2被跳过了2次,此时可以认为2号丢失,不用等超时,直接重传2号包,可以大大改善了丢包时的传输速度。&/li&&li&延迟ACK vs 非延迟ACK:TCP为了充分利用带宽,延迟发送ACK(NODELAY都没用,有些系统可以微调,但是是改注册表全局值,不太好),这样超时计算会算出较大 RTT时间,延长了丢包时的判断过程,我们对ACK是否延迟发送可以实时调节(也可以根据交互模式还是单向传输模式来抉择,或者给用户开关选择)。&/li&&li&UNA vs ACK+UNA:ARQ模型响应有两种,UNA(此编号前所有包已收到,如TCP)和ACK(该编号包已收到),光用UNA将导致全部重传,光用ACK则丢失成本太高,以往协议都是二选其一,而实现一套更好的协议,除去单独的 ACK外,可以让所有包都有UNA信息,得到更好效果。&/li&&li&流控改进:传统 TCP 都是基于退让的流控,现代 TCP 不停的再改退让法则,其实限制于 TCP 的兼容性他们才跳不出来这个坑,如果完全抛开 TCP 协议,各种现代传输协议都是使用前面提到的带宽估计和网络质量评估来代替流控的。&/li&&li&窗口初始大小:用不着象传统 TCP 协议那样死板,每次建立新连接或者远端窗口探测的过程都让窗口设置成1,可以直接设置成更高值了。&/li&&/ul&&p&协议层优化结合前面的冗余和信道质量评估,跳出 TCP 的限制,以牺牲部分公平性和降低部分带宽利用率的代价,可以得到更低的传输延迟。&/p&&p&这部分我开源了,欢迎访问:&a href=&//link.zhihu.com/?target=https%3A//github.com/skywind3000/kcp& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&skywind3000/kcp&/a&&/p&&p&&br&&/p&&p&&b&路由层优化:路由实时评估&/b&&/p&&p&公网提供的路由并不是最佳的,书上虽然说路由就是要找最优通路,实际情况是,最优通道价格高,屌丝用户就走走免费的省道国道得了,高富帅再走高速。因此你需要建立自己的全局路由系统。对全局网络有一个比较明确的评估。&/p&&p&&br&&/p&&p&&b&路由层优化:路由动态选择&/b&&/p&&p&根据前面的实时路由评估结果,使用空闲用户帮忙转发以及 IDC 布点的模式,决策最佳的传输路径,并且考虑线路冗余(同一个时刻保持两条以上的通路,一条挂了实时切换到另外一条)。每两三个路由节点之间,采用三角连接法,每个节点至少保证两条线路:&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-3c302fc69fc9a46679d1_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&686& data-rawheight=&337& class=&origin_image zh-lightbox-thumb& width=&686& data-original=&https://pic4.zhimg.com/50/v2-3c302fc69fc9a46679d1_r.jpg&&&/figure&&p&不要以为网络上地理位置越近的传输速度越快,也不要以为跳数越少传输速度越快,实际情况是,正确的选择路由,即便跳数增加,也能极大的提升传输速度。&/p&&p&&br&&/p&&p&&b&物理层传输优化&/b&&/p&&p&是用更好的传输介质(比如光纤),或者增加传输功率,又或者再功率不变的情况下使用低频信号(但是低频信道带宽一般不高),都能降低信号损失。一般来讲,可以通过评估信号衰减来自动增加减少功率,实时切换使用高低频信道。或者更换天线或者信号源位置让衰减最低(好像有点扯远了)。。。&/p&&p&使用吞吐量更大的设备,同样成本下一般带宽,每秒发包数,RTT三者不可得兼,根据情况选择擅长 RTT 或者带宽的设备。&/p&&p&&br&&/p&&p&&b&应用层带内冗余:低频数据冗余&/b&&/p&&p&比如你在传送一段音频的话,比如每秒 40 个数据帧,用类似 MP3 的压缩方法,那么你可以将每秒的音频分作 40 段,每段 25ms,然后进行 DCT ,滤波,量化,无损压缩等几个传统步奏后,得到一段类似 mp3 的25ms的数据,我们叫一帧,发包的时候,除了包含这一帧的数据外,还同时包含上几帧的低频数据,这样对带宽增加不大,然而我们再解码的时候,如果发现丢包就可以用其他包含有的本帧低频数据,还原出一个质量没有原来好,但是听起来差不多的数据,这叫低频数据冗余。&/p&&p&&br&&/p&&p&&b&应用层带内冗余:DSP处理&/b&&/p&&p&这是更高级的处理方式,比如你在传输视频,视频中最费带宽的是 I 帧数据,即便 H.265,I帧数据比较其他帧也是很大的。然而 H.264, H.265 系列并没有很好的考虑容错和抗损坏。我们可以用帮他们在这方面做的更好一些,才用频域交错存储及其他一些方法,比如把一幅质量为 70% 大小为 32KB 的 I 帧图像,存储成两张质量为 40% 大小为 16KB - 18KB 的 I 帧图像,两个拆分后的图像单独看,都是一副质量更低的图片,但是他们组合起来,却能变成一张质量很好的图片。这样对于传输视频而言,I帧的瓶颈就不那么明显了,即时丢了一半,也只是损失一下效果而已。&/p&&p&修改 H.264/ H.265的方法有很多,上面只是举个例子。如果你传送的是视频数据的话,你可以找一找相关的文章,教你改进 H.264, H.265。同样如果你传 AAC的话,也有很多方法在带内实现冗余。&/p&&p&上面说的各种带外冗余主要是要 “增加带宽”, 而应用层的 “带内冗余” 主要思路是丢包了就降低质量,在带宽收到限制的时候,我们往往需要果断的使用各种带内冗余法,来保证较流畅的传输体验。&/p&&p&&br&&/p&&p&&b&应用层误差掩盖&/b&&/p&&p&传送视频数据发现局部丢失了,可以用前后两帧画面以及周围的图块来推断丢失的图块可能是什么,然后模拟生成一下,要比直接马赛克好很多。&/p&&p&传送音频数据发现局部丢失了,可以用前后音频频域插值模拟出丢失的声音片段,也可以通过学习的方式,通过前面历史数据的基音和共振峰提取,来模拟丢失的声音。&/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-9d9f69d5759cf37ecc5c1cea018d1379_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&423& data-rawheight=&242& class=&origin_image zh-lightbox-thumb& width=&423& data-original=&https://pic2.zhimg.com/50/v2-9d9f69d5759cf37ecc5c1cea018d1379_r.jpg&&&/figure&&p&即便不模拟,还有方法是通过生成一段舒适的背景噪音来填充丢失的片段,这样会比直接空白音好很多,或者通过不改变基音却变慢语速的方式,让前后两段声音接起来,这样你听着就是声音慢了几十毫秒,但是很连续,发现不了其中丢失。&/p&&p&比如你传送游戏数据的话,一般位移数据可以用非可靠传输方式来传输,每组移动数据不但包含坐标和方向,还要包括时间和速度,这样,数据丢失了,你从后面的数据恢复出来以后,画面上做一个移动差值(导航推测),立马就能掩盖这次传输误差。&/p&&p&所谓应用层误差掩盖,是根据你的应用特点来设计规则,即便传输数据丢失,你也能通过各种模拟和插值的方式掩盖过去,只要保证后来的数据能够修正即可,这样即便信号不好,出现短时误差了,也能得到即时的纠正。&/p&&p&&br&&/p&&p&&b&应用层延迟控制&/b&&/p&&p&数据包前后顺序依赖(Pn依赖 Pn-1)可以进化为交错依赖(Pn依赖 Pn-2,Pn+1 依赖 Pn-1),这样丢包发生只会导致一部分后续数据无法工作,而不会导致某一时间内所有后续数据没法工作。&/p&&p&控制缓存策略,缓存小了延迟低但是效率也低,缓存大了延迟高,效率也高。网络拥塞了缓存怎么办?使用更少的往返次数来实现交流。&/p&&p&&br&&/p&&p&。。。。。。&/p&&p&&br&&/p&&p&&b&总结&/b&&/p&&p&所谓 “降低延迟”,其实就是 “提高通信质量”,这个问题通信行业一直在研究解决的事情,不可能靠单方面的技巧提高很多(比如冗余),这是一个系统工程,有它的理论体系,有它的实践方法,还有各种注意事项。&/p&&p&&br&&/p&&p&----&/p&
这是通信领域的话题了,低延迟传输有上百种优化方式,上面说的那些冗余码只是很小一部分,不考虑信道容量的冗余编码系统都是在耍流氓,不用等到同信道内跑两套这样的协议你才会发现问题,一套协议再接近信道带宽容量限制时,就会出现指数上升的丢包率,所以…
&p&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-ced055a105_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2160& data-rawheight=&1216& class=&origin_image zh-lightbox-thumb& width=&2160& data-original=&https://pic2.zhimg.com/v2-ced055a105_r.jpg&&&/figure&&p&&br&&/p&&h2&前言&/h2&&blockquote&写完这篇文章后已经卸载了PUBG,删除了虚拟机及相关文件,释放了服务器,本文仅仅是对我过去几天所遇到的一些问题的记录&br&&/blockquote&&p&&br&&/p&&ul&&li&已在steam中卸载:&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-24f51cfe85aac9b0ac5ea2_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1104& data-rawheight=&660& class=&origin_image zh-lightbox-thumb& width=&1104& data-original=&https://pic3.zhimg.com/v2-24f51cfe85aac9b0ac5ea2_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&ul&&li&已经删除win7虚拟机:&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-b068c161704bed1b1d901ce2b6282986_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1532& data-rawheight=&960& class=&origin_image zh-lightbox-thumb& width=&1532& data-original=&https://pic3.zhimg.com/v2-b068c161704bed1b1d901ce2b6282986_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&ul&&li&已经释放掉相关服务器:&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-7e536c06fee_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2560& data-rawheight=&1424& class=&origin_image zh-lightbox-thumb& width=&2560& data-original=&https://pic2.zhimg.com/v2-7e536c06fee_r.jpg&&&/figure&&p&&br&&/p&&p&这篇文章写完时是,截止到现在,本文谈及的几种方式依然适用,并且我从未被封号&/p&&p&下面开始正文内容:&/p&&p&虽然吃鸡火了很长一段时间了,但最开始接触吃鸡这个游戏是在寒假和朋友们一起吃鸡开黑吧。于是98买了个号然后踏上了我的“求生”之旅,到现在打了一个多月,玩了200小时,发现这个游戏只要分高点,神仙(挂壁)是真的多,都不带演的,而且甚是暴力,除了一般fps游戏常见的自瞄、透视,吃鸡的火爆程度与利益巨大的产业链带来了各式各样的外挂:&br&&a href=&http://link.zhihu.com/?target=http%3A//www.sohu.com/a/6298& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&sohu.com/a/&/span&&span class=&invisible&&6298&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-e9f8c7bede3322bce3bae4_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&197& data-rawheight=&159& class=&content_image& width=&197&&&/figure&&p&&br&&/p&&p&求生欲促使我开始了我的求生之路。在网上甚至游戏LeadBorad里,有各种卖挂加群什么的,但是稳定性未知,感觉会很容易被封号。其次,外挂的价格都不便宜,听说8元一小时?甚至&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-368cd26a046c170de43c98_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&598& data-rawheight=&565& class=&origin_image zh-lightbox-thumb& width=&598& data-original=&https://pic1.zhimg.com/v2-368cd26a046c170de43c98_r.jpg&&&/figure&&p&&br&&/p&&p&顺便说一句:开挂有风险,买挂需谨慎,尤其当心骗子。&br&知乎:21岁的少年贩卖游戏外挂都日入万元了!你还在往游戏里充钱?&br&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/p/29&/span&&span class=&invisible&&173323&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&不愧是黑产,这价格从来都不让我失望,那么我这种穷逼怎么办?于是我来到全球最大的同性交友网站github需求帮助,发现了几个不错的开源项目。&/p&&blockquote&在介绍我的科学吃鸡之路之前,先简单介绍下传统的外挂,以更好的突出后面要介绍的通过嗅探数据包的方式实现透视的优势所在,你可以略过这部分直接到后面看我是如何配置部署透视的&br&&/blockquote&&h2&传统外挂&/h2&&p&fps游戏都有一个共同的特点,大部分计算都是本地完成的,不可能每一个动作都和服务器交互,有几个原因:&/p&&p&&br&&/p&&ul&&li&会造成服务器负荷过大,提高运营成本&/li&&li&在对枪杀人时,几十ms的延迟可能会扭转战局&/li&&li&会极大影响游戏体验&/li&&/ul&&blockquote&信息安全的一个基本原则,永远不要相信用户的输入。这里的输入就是指在本地进行运算的结果。本地进行的计算越少,与服务器交互的越多,外挂利用难度更大。&br&&/blockquote&&p&由于大量的计算都是在本地完成的,而游戏又是运行在内存中,那么导致了我们有很多种方法进行利用。最简单的就是用CE修改内存里的数据,常规的有注入和Hook,还有各种奇淫技巧。单以注入为例,就有五花八门的注入技术。下面是《游戏外挂攻防艺术》一书中的提到的一些方法&/p&&p&&br&&/p&&ul&&li&注册表注入&/li&&li&远线程注入&/li&&li&依赖可信进程注入&/li&&li&APC注入&/li&&li&消息钩子注入&/li&&li&导入表注入&/li&&li&劫持进程创建注入&/li&&li&LSP劫持注入&/li&&li&输入法注入&/li&&li&ComRes注入&/li&&/ul&&h2&修改本地文件的PUBG外挂&/h2&&blockquote&由于我并没有开发过绝地求生的外挂,也没有仔细研究分析过程序,以下说法纯粹为个人在网上道听途说,外加一点点瞎猜。如果哪里说错了,各位就当做笑话看看吧&br&&/blockquote&&p&在网上看过几篇绝地求生外挂的帖子,大致都是通过修改游戏资源文件(.pak),来实现的各种功能,而PUBG采用BattlEye来实现反外挂,游戏运行时后台有个叫BEservice.exe的进程,进游戏后打开任务管理器就能看到两个很明显的PUBG logo的进程,另外一个叫TslGame.exe是游戏的进程。BEservice.exe对PAK修改的检测十分严格,而且不断在更新,这也是各种辅助有时在游戏更新后会失效的一个主要原因。而基本上一个外挂失效,也只用更新下过检测(BEservice.exe),就能满血复活了。关于过检测的一些旧方法,可以看大佬的经验分享(需要登陆吾爱破解的账号才有权限查看):&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//www.52pojie.cn/thread--1.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&52pojie.cn/thread-70375&/span&&span class=&invisible&&7-1-1.html&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&但是我从来没用过这种靠在本地的修改来获取仙力的外挂,因为:&/p&&p&&br&&/p&&ul&&li&我觉得这是很容易被检测到的,因为BattlEye的外挂检测机制对于我们来说是一个黑盒,我们不可能总是怀着侥幸心理,希望不被检测到。&/li&&li&这种多人fps游戏,其实一个透视就够了,而透视不一定要通过修改本地文件实现,可以对游戏的数据包进行嗅探分析实现,不像其他一些功能,如:自瞄,路飞挂,穿墙,无后,遁地什么乱七八糟的,大多都是必须要修改本地文件的&/li&&/ul&&blockquote&由于使用修改本地文件实现的外挂风险特别大,所以我选择了一种更不容易被PUBG察觉的方式,嗅探网络流量&br&&/blockquote&&h2&嗅探网络流量包的PUBG外挂&/h2&&p&首先,说下这种外挂为什么不容易被检测,更加稳定。&/p&&h2&大致原理&/h2&&blockquote&这里我们称运行PUBG的电脑为“游戏机”,嗅探流量实现透视的为“中间机”。&br&&/blockquote&&p&正常玩游戏时,我们的网络拓扑图是这样的&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-47faaffd9621_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&500& data-rawheight=&160& class=&origin_image zh-lightbox-thumb& width=&500& data-original=&https://pic2.zhimg.com/v2-47faaffd9621_r.jpg&&&/figure&&p&&br&&/p&&p&在局域网中使用中间机嗅探流量后:&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-3ef74cd502b2ab2e6ebf810_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&589& data-rawheight=&160& class=&origin_image zh-lightbox-thumb& width=&589& data-original=&https://pic1.zhimg.com/v2-3ef74cd502b2ab2e6ebf810_r.jpg&&&/figure&&p&&br&&/p&&p&更高级点,也是我现在用的,买一个国外服务器,部署透视和Shadowsocks服务,同时实现游戏网络加速、透视加科学上网的效果&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-4dc6d0508a5dae7af9737_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&584& data-rawheight=&160& class=&origin_image zh-lightbox-thumb& width=&584& data-original=&https://pic4.zhimg.com/v2-4dc6d0508a5dae7af9737_r.jpg&&&/figure&&p&&br&&/p&&p&总的来说,个人认为通过嗅探网络流量包实现的透视有以下几个优势:&/p&&p&&br&&/p&&ul&&li&游戏机(运行PUBG的电脑)并不需要修改任何文件,使用任何软件,不用担心被本地检测,封号等&/li&&li&服务端无法察觉这种嗅探,因为嗅探的前后只会有小到可以忽略不计的延迟差异&/li&&li&实现分屏,游戏与透视分开,这种十分适合主播用,大家看过直播都懂的,主播们偶尔假装看下弹幕,你们怎么知道他是真的在看弹幕呢?然后还有各种开镜必有人的操作&/li&&li&不易被和谐,除非蓝洞加密通讯过程,或者更改通讯协议。但是通过逆向工程还是很容易去分析,改写的。除了投入大量人工成本去不断的更新以获得短期的和谐,蓝洞应该是没什么太好的办法去阻止这种通过嗅探完成的透视&/li&&/ul&&p&我并没有自己对PUBG的通信协议进行分析,于是我上全球最大的同性交友网站搜索有没有轮子,果然发现了几个近段时间热门的开源项目。有以下几个仓库很不错:&/p&&p&Kotlin版本:&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/Jerry1211/RadarProject& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/Jerry1211/Ra&/span&&span class=&invisible&&darProject&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&nodejs版本:&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/txchen/scichicken& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/txchen/scich&/span&&span class=&invisible&&icken&/span&&span class=&ellipsis&&&/span&&/a&&/p&&h2&Kotlin版本&/h2&&p&这是我最开始所尝试的,透视界面大致为:&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-aae8fd811aa54244f4bab21e6a5fbf69_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1894& data-rawheight=&1010& class=&origin_image zh-lightbox-thumb& width=&1894& data-original=&https://pic2.zhimg.com/v2-aae8fd811aa54244f4bab21e6a5fbf69_r.jpg&&&/figure&&p&&br&&/p&&p&各种物资车辆人物透视应有尽有,项目Readme里面有详细的部署过程,且分为两种方式:&/p&&p&&br&&/p&&ul&&li&单机版:运行PUBG的游戏机后台再开一个虚拟机,但是这种还是比较容易被检测到的。听说现在只要检测到VM的进程直接就给你把游戏关了,我也从没尝试过这种办法&/li&&li&双机版:需要两台电脑,两台电脑使用网线或者VPN或者其他什么方式将网络相互连接起来,让游戏机的网络流量通过中间机,中间机就行嗅探并转发&/li&&/ul&&p&下面简单介绍下我的双机版部署过程,也可以参考:&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//docs.google.com/document/d/1hrmnwMoVWmH7GTRwHEeOpGHgehKsETgJRQTacAtgIHQ/edit& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&docs.google.com/documen&/span&&span class=&invisible&&t/d/1hrmnwMoVWmH7GTRwHEeOpGHgehKsETgJRQTacAtgIHQ/edit&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&首先介绍下我的运行环境:&/p&&p&&br&&/p&&ul&&li&游戏机:组装台式电脑 + win10 + PUBG&/li&&li&中间机: MacBook Pro + VMware Fusion + win7 ultimate&/li&&li&连接方式:由于MacBook没有网线插口,我又没有usb网卡,所以我通过局域网VPN的方式连接&/li&&/ul&&p&win7是运行在MacBook的虚拟机上的,设置虚拟机的网络适配器为桥接,使其和游戏机同处于路由器的局域网环境下。在win7上,我们部署透视:&/p&&p&&br&&/p&&ul&&li&安装Java,配置系统环境变量,网上教程一大堆,自己搜吧&/li&&li&安装Maven,并配置所需要的环境变量,参考官网的安装介绍就行了:&a href=&http://link.zhihu.com/?target=https%3A//maven.apache.org/install.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&maven.apache.org/instal&/span&&span class=&invisible&&l.html&/span&&span class=&ellipsis&&&/span&&/a&&/li&&li&设置环境变量&code&MAVEN_OPTS&/code&为&code&-Xms256m -Xms2048m&/code&&/li&&li&&code&git clone https://github.com/Jerry1211/RadarProject.git&/code&&/li&&li&在项目根目录下,使用命令&code&mvn verify install&/code&进行打包编译&/li&&/ul&&p&然后我们在target文件夹下 会多出一个jar包&code&RadarProject-Jerry1211-FORK-jar-with-dependencies.jar&/code&,就OJBK了。&/p&&p&接着是配置我们的网络,使中间机能嗅探游戏机流量。&/p&&h2&中间机:&/h2&&p&&br&&/p&&ul&&li&网络与共享中心-更改适配器设置&/li&&li&按一下&code&ALT&/code&打开左上角菜单-文件-新建传入连接&/li&&li&按照提示选择用户什么的,然后选择IPv4的属性&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-1bcb0c0afba366211efbbc8622ede26d_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&952& data-rawheight=&682& class=&origin_image zh-lightbox-thumb& width=&952& data-original=&https://pic2.zhimg.com/v2-1bcb0c0afba366211efbbc8622ede26d_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&ul&&li&根据自己的网络环境配置一下&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-986f9b7cdf_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&616& data-rawheight=&446& class=&origin_image zh-lightbox-thumb& width=&616& data-original=&https://pic4.zhimg.com/v2-986f9b7cdf_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&ul&&li&控制面板-系统和安全-Windows防火墙-高级设置&/li&&li&入站规则-新建规则&/li&&li&选择“端口”,下一步&/li&&li&选择tcp,指定端口1723,其他的都默认&/li&&li&入站规则-新建规则&/li&&li&选择“自定义”,下一步&/li&&li&“协议和端口”中“协议类型”一项选择“GRE”,其他的都默认&/li&&/ul&&h2&游戏机:&/h2&&p&&br&&/p&&ul&&li&window设置-网络和Internet-vpn-添加一个VPN连接,服务器地址写win7的局域网地址&/li&&li&填好账号密码,然后连接&/li&&li&运行PUBG&/li&&/ul&&h2&启动透视&/h2&&p&在win7中,我们已经编译好了项目,我们用命令去运行,注意替换这里的两个ip,ip可以用命令&code&ipconfig&/code&查看 :&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&java -jar target\RadarProject-Jerry1211-FORK-jar-with-dependencies.jar &Middle PC IP& PortFilter &Game PC IP&
&/code&&/pre&&/div&&p&如果没什么问题的话,应该会出现一个新的窗口程序,上面是灰着的,那么离成功就差最后一步了。回到游戏机,运行游戏,这时应该能在win7中看到地图和人物透视了&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-ec57df2a0c44ad4130893c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1920& data-rawheight=&1080& class=&origin_image zh-lightbox-thumb& width=&1920& data-original=&https://pic1.zhimg.com/v2-ec57df2a0c44ad4130893c_r.jpg&&&/figure&&p&&br&&/p&&h2&可能遇到的问题&/h2&&p&&br&&/p&&ul&&li&游戏启动后,程序还是灰着的:请检查ip地址是否正确,多尝试几次&/li&&li&加速器问题:网上说是可也用加速器的,但是得是虚拟一个网卡的那种,然后游戏机ip就填虚拟出的那个网卡的ip,如海豚加速器模式二,网易UU加速器模式三,我去注册了账号,领了试用的,然后试了一下,并没有成功&/li&&li&游戏Server too busy:没用加速器的原因,多重试几次就行了&/li&&li&没有NUMPAD(右边的小键盘)去开启关闭游戏的一些功能:用Windows自带的小工具“屏幕键盘”,选项中打开小键盘&/li&&/ul&&h2&nodejs版本&/h2&&p&上面那个版本需要在win7中运行,虽然好像更新过有MACos和Linux的配置文件,但是我编译安装一直失败。而我没有多的windows的电脑,只能用MacBook开一个win7虚拟机的方式去嗅探、实现透视,这种做法十分费电、且烧电脑,而且本身就是一个抓包嗅探,分析数据包,再用UI显示出来的过程,并不需要一定要用Windows系统。然后我发现了这个用nodejs实现的版本,比起上一个,我更喜欢这个,原因如下:&/p&&p&&br&&/p&&ul&&li&在三大操作系统(Windows,Liunx,MACos)上能很方便的部署运行,不会遇到太多问题&/li&&li&UI使用Web服务,只要用浏览器访问指定ip和端口就行了&/li&&li&界面更友好,物资显示更清楚、明朗,方便的开关&/li&&/ul&&p&效果图如下,这是没开比赛的,开始比赛后才会显示人物,物资:&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-b110166dca01a9c162ac4410801eaa14_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2560& data-rawheight=&1416& class=&origin_image zh-lightbox-thumb& width=&2560& data-original=&https://pic1.zhimg.com/v2-b110166dca01a9c162ac4410801eaa14_r.jpg&&&/figure&&p&&br&&/p&&h2&在MacBook上部署&/h2&&blockquote&部分命令请根据自己的网卡名称和网络环境自行修改&br&&/blockquote&&p&&br&&/p&&ul&&li&首先,安装nodejs和npm,并更新到最新版&/li&&li&允许转发流量&/li&&li&&code&sudo sysctl -w net.inet.ip.forwarding=1&/code&&/li&&li&&code&echo &nat on en0 inet from 192.168.1.0/24 to any -& 192.168.1.141& | sudo pfctl -v -ef -&/code&&/li&&li&克隆项目,部署安装&/li&&li&&code&git clone https://github.com/txchen/scichicken.git&/code&&/li&&li&&code&cd scichicken&/code&&/li&&li&&code&npm i&/code&&/li&&li&&code&npm i -g pino&/code&&/li&&li&运行项目&/li&&li&&code&node index.js sniff en0 192.168.1.200 | pino&/code&&/li&&/ul&&h2&设置游戏机网关&/h2&&p&&br&&/p&&ul&&li&网络与共享中心-更改适配器设置&/li&&li&选择你的适配器-右键属性-IPv4-属性&/li&&li&这里我设置ip地址为&code&192.168.1.200&/code&,网关设置MacBook的局域网地址,再随便搞个DNS地址上去,大概这样子&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-db4477eca197c6b2b1fe008_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&606& data-rawheight=&630& class=&origin_image zh-lightbox-thumb& width=&606& data-original=&https://pic1.zhimg.com/v2-db4477eca197c6b2b1fe008_r.jpg&&&/figure&&p&&br&&/p&&p&不出意外的话,你运行游戏后就能看到效果了&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-530e56812dbeee710cc11_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1080& data-rawheight=&1920& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic2.zhimg.com/v2-530e56812dbeee710cc11_r.jpg&&&/figure&&p&&br&&/p&&p&但是怎么用加速器还是个问题,因为没有加速器的话,打起来毫无游戏体验。反正这个UI是使用Web服务的,索性把他部署到服务器上,然后随便找个设备用浏览器看不就行了。下面我将介绍本篇文章的重点:如何打造一台 “科学上网+游戏加速器+透视” 三合一的服务器。这也是我觉得最稳定,最方便,最好用的一种方式。&/p&&h2&打造自己的 “科学上网+游戏加速器+透视” 三合一服务器&/h2&&h2&选择服务器&/h2&&p&首先服务器的地区要选择没有墙的,然后延迟也要低,且稳定,才能达到游戏的加速效果。我选择了阿里云的香港服务器,配置信息如下:&/p&&p&&br&&/p&&ul&&li&CPU: 2核&/li&&li&内存: 8 GB&/li&&li&带宽计费方式: 按使用流量&/li&&li&当前使用带宽: 25Mbps(峰值)&/li&&li&操作系统: CentOS 7.4 64位&/li&&/ul&&p&当然,就一个简单的web服务,一般是不需要这么高的配置的,因为我是按流量计费,而且本来就是弄个服务器来研究一下的,没准备长期用,所以我选择了稍高点的配置,至于价格,玩一天也就大概一元RMB多点吧&/p&&h2&使用Shadowsocks链接服务器&/h2&&p&有了服务器,我们下一步就是想办法把游戏机链接到服务器,让服务器能嗅探到游戏的数据包,这里有很多种办法,如vpn、V2ray等,这是我使用较为简便的Shadowsocks。ssh链接上去执行以下命令&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&wget --no-check-certificate -O shadowsocks-all.sh https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocks-all.sh
chmod +x shadowsocks-all.sh
./shadowsocks-all.sh 2&&1 | tee shadowsocks-all.log
&/code&&/pre&&/div&&p&然后我选择python语言的,因为其支持udp转发,接着设置好密码,端口及加密方式,脚本会自动帮你安装完成。&/p&&p&安装好后,我们需要在阿里云的云服务器管理控制台更改下安全组规则,放行你的ss服务端口和项目的默认端口20086,如下:&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-562b09d8bc8fb4a09ff29d322fd83ce5_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1814& data-rawheight=&488& class=&origin_image zh-lightbox-thumb& width=&1814& data-original=&https://pic2.zhimg.com/v2-562b09d8bc8fb4a09ff29d322fd83ce5_r.jpg&&&/figure&&p&&br&&/p&&p&这时用游戏机试试能不能正常转发游戏的数据包以获得加速效果。然而ss的客户端是不支持udp转发的,所以我们下载软件&code&SSTap&/code&,网址:&a href=&http://link.zhihu.com/?target=https%3A//www.sockscap64.com/sstap/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&sockscap64.com/sstap/&/span&&span class=&invisible&&&/span&&/a&&/p&&p&安装好后,添加一个ss代理,根据你刚才填写的信息配置好,模式选择绝地求生,点击闪电符号测试一下udp转发,我们可以看到,阿里云的香港节点延迟还是很不错的,不亚于一些主流的加速器了,这时你可以把它当作一个游戏网络加速器去使用了,或者用他去看一看墙外的世界&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-d6ed53bd8fa57f38986f9_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1528& data-rawheight=&1094& class=&origin_image zh-lightbox-thumb& width=&1528& data-original=&https://pic2.zhimg.com/v2-d6ed53bd8fa57f38986f9_r.jpg&&&/figure&&p&&br&&/p&&h2&安装nodejs和npm&/h2&&p&我使用NVM(Node version manager)进行安装:&/p&&p&&br&&/p&&ul&&li&下载并安装NVM脚本&/li&&li&&code&curl https://raw.githubusercontent.com/creationix/nvm/v0.13.1/install.sh | bash&/code&&/li&&li&&code&source ~/.bash_profile&/code&&/li&&li&选择版本安装,我选择v9.8.0&/li&&li&&code&nvm install v9.8.0&/code&&/li&&li&设置默认版本&/li&&li&&code&nvm alias default v9.8.0&/code&&/li&&/ul&&p&检查一下安装成功没&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-f63e0deb5c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&570& data-rawheight=&176& class=&origin_image zh-lightbox-thumb& width=&570& data-original=&https://pic1.zhimg.com/v2-f63e0deb5c_r.jpg&&&/figure&&p&&br&&/p&&h2&安装libpcap&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&yum -y install gcc-c++
yum -y install flex
yum -y install bison
wget http://www.tcpdump.org/release/libpcap-1.8.1.tar.gz
tar -zxvf libpcap-1.8.1.tar.gz
cd libpcap-1.8.1
./configure
make install
&/code&&/pre&&/div&&h2&安装部署项目&/h2&&p&这里的网卡名称和ip地址根据自己的网络环境修改,,其中ip地址不是公网地址,是服务器的私有地址,也就是你ifconfig看到的那个&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&yum install git
git clone https://github.com/txchen/scichicken.git
cd scichicken/
npm i -g pino
node index.js sniff eth0 172.31.***.*** | pino
&/code&&/pre&&/div&&p&然后浏览器访问一下 &code&http://47.75.***.***:20086/&/code&,这里的ip是你服务器的公网地址,端口默认为20086。如果没什么问题,应该能正常显示页面了。&/p&&p&最后,我偏爱于将这个进程放到后台去运行,好让我去做一些其他操作,所以我是这么启动的:&/p&&p&&code&nohup node index.js sniff eth0 172.31.***.*** | pino & Pubglog.txt &&/code&&/p&&h2&体验&/h2&&p&我用这种方式体验了几把,效果还是很不错的,有以下几点:&/p&&p&&br&&/p&&ul&&li&很好的解决了游戏的延迟问题,而且阿里云的服务器,网络延迟也贼稳定&/li&&li&由于透视是通过web服务展现的,你可以将地址分享给队友,然后就相当于一个小队4人都开启了透视,但他们看到的都是你的视角。不过一般一个小队都不会走的太散,基本是没有影响的&/li&&li&我是佛性吃鸡的,不万不得已不杀人,就到处走野区搜搜东西吧,给大家看看我的场均装备&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-32e6aefed8ea_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2160& data-rawheight=&1216& class=&origin_image zh-lightbox-thumb& width=&2160& data-original=&https://pic3.zhimg.com/v2-32e6aefed8ea_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&ul&&li&一定意义上的解决了跨平台,分屏等需求,你可以在任何终端上查看网页比如:笔记本,平板,手机等&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-ced055a105_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&2160& data-rawheight=&1216& class=&origin_image zh-lightbox-thumb& width=&2160& data-original=&https://pic2.zhimg.com/v2-ced055a105_r.jpg&&&/figure&&p&&br&&/p&&p&不过使用之后,感觉还是平板最方便,因为笔记本太大了,占位置,手机屏幕又太小了,如果不横屏,右边只有一小块是显示出来。&/p&&blockquote&值得一提的是,这种方式也极大的方便在直播中作弊:假装拿起手机看看微信,看看弹幕什么的,观众是很难察觉的。&br&&/blockquote&&h2&顺便谈谈鼠标宏&/h2&&p&鼠标宏我也是用过的,github上也有几个不错的开源项目,如:&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//github.com/liantian-cn/logitech-pubg& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/liantian-cn/&/span&&span class=&invisible&&logitech-pubg&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&一般是需要罗技的鼠标的,我的是G502。不过弄好打了一局后发现根本不好用,这枪越压越飘,还不如没用压的好,然后就删了&/p&&h2&最后的声明&/h2&&p&&br&&/p&&ul&&li&首先说明,本人从未参与任何外挂开发,制作过程,只是看到几个开源项目,然后部署试用了一下,用完后现已将所有有关文件删除,虚拟机删除,相关服务器也已经释放了&/li&&li&本人从未使用任何外挂获取一分钱的盈利,也从未向他人分享过外挂使用,本人只是作为研究目的尝试使用过几把&/li&&li&请勿将本文所谈到的办法用于任何商业目的&/li&&li&本文只是分享我的部署过程,及使用中碰到的一些问题,并不是鼓励大家去开挂&/li&&li&个人也很反感外挂,每次搜了一大波野区,苟了半天,然后就都送快递给神仙了&/li&&li&我知道很多人会喷我开挂,但是在我这开挂测试的几把里,为了其他玩家的游戏体验,我一般都是尽可能都是绕着他们走的,贯彻佛性吃鸡。&/li&&/ul&
前言写完这篇文章后已经卸载了PUBG,删除了虚拟机及相关文件,释放了服务器,本文仅仅是对我过去几天所遇到的一些问题的记录 已在steam中卸载: 已经删除win7虚拟机: 已经释放掉相关服务器: 这篇文章写完时是,截止到现在,本文谈及的几种方式依…
水木有人批过 muduo,我看了他说的几个问题,还是站得住的,不过 muduo 的代码我没看过。我的看法是,这种东西看着学习学习是可以的,真用,要么用一层薄薄的封装如 libevent 之类,要么完全自己搞(做一个网络框架并不特别费力),你会发现,复杂的地方不在框架可以处理的那里。&br&&br&补充说明一下我对那位水木网友的看法的看法,我认为他关于 timer 的批判是站得住脚的---如果他说的属实的话,关于 signal 的看法有待商榷,实屏蔽大部分 signal(只留一个做启停)是实践上很实用的做法,一般也不特别需要网络框架去处理。&br&&br&-------------------------------&br&这是那位水木网友的文章:&br&&p&
hurricanelee (风的影子) 于
(Tue Sep 25 13:57:06 2012)
提到:&/p&&br&&p&muduo适用于什么环境?&/p&&br&&p&muduo的官方一句话自我介绍是:A C++ non-blocking multi-threaded network&/p&&p&library for Linux。&/p&&p&在其readme和wiki中均未提及此lib是否适用于实际场景,于是我花了些时间翻看了一&/p&&p&下,得出的结论是此lib仅限于展示epoll/poll的基本用法,对网络编程初学者是否有参考&/p&&p&价值还有待进一步考察。&/p&&br&&p&任何一个网络产品除了要支持网络event之外,还必须处理另外两种事件:signal和&/p&&p&timer。&/p&&p&muduo也毫无例外。但近看一下就发现muduo对single和timer的支持很有喜感。&/p&&br&&p&除了SIGPIPE被mask之外,muduo没有接管signal。当然muduo这么做是有借口的,反&/p&&p&正有signalfd嘛。在此我想问问各位做网络应用的同学,在你的实际项目中,不用POSIX&/p&&p&的signal接口而用signalfd的,有几个?而如果是从编程初学者教育的角度来看,是介绍&/p&&p&POSIX重要,还是介绍2.6.22引入的一个new feature重要?&/p&&p&而抛弃signal的处理之后,muduo自然轻松了许多,还顺带可以说一句:muduo支持高&/p&&p&级特性signalfd。--嗯,听起来很高级,不过signalfd不是muduo支持的,而是kernel支&/p&&p&持的。&/p&&br&&p&一个网络编程库,timer是重中之重,比到底是用epoll还是select都重要。当然,话说回&/p&&p&来,再吊的库无非也就是个heap为本的数据结构在支持,无非是有些库喜欢说自己的&/p&&p&heap实现比别人都高效,比如haproxy。&/p&&p&但muduo却独辟蹊径,用timerfd,泥玛又是一个高级特性啊,很唬人的。由kernel帮你&/p&&p&管理timer,是不是很吊。&/p&&p&不仅采用了timerfd,muduo还采用了set来保存event,每个big loop里要查超时的时&/p&&p&候,再iterate一遍这个set。&/p&&p&再然后,每次加一个timer,就要冒着一次settime的syscall的风险--这还不够,还得要一&/p&&p&次gettimeofday。别不把syscall当不要钱的可以吗?&/p&&p&你也许可以跑10万个连接,但你敢加上超时的特性吗?muduo如果有做过细致的&/p&&p&benchmark就会知道,一个loop里最花时间的就是timer的处理。&/p&&p&关于muduo的timer处理,槽点太多,我就不一一细述了。回头看看timer,很显然不适&/p&&p&合工业应用,而给初学者做参考。。。嗯,负面参考价值很大。&/p&&br&&p&嗯,今天先说这么多吧。吐槽点还很多,比如那个全功能的http范例,比如对&/p&&p&pthread/fork的支持,比如对内存的使用等等等等。都要一一吐过也不是不可以,不过就&/p&&p&要耐下性子来慢慢写就是。&/p&&br&&p&反正没人知道我是谁=D,欢迎拍砖打脸&/p&&br&&p&转自:&a href=&//link.zhihu.com/?target=http%3A//pastebin.com/8S7CjdSb& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&pastebin.com/8S7CjdSb&/span&&span class=&invisible&&&/span&&/a&&/p&
水木有人批过 muduo,我看了他说的几个问题,还是站得住的,不过 muduo 的代码我没看过。我的看法是,这种东西看着学习学习是可以的,真用,要么用一层薄薄的封装如 libevent 之类,要么完全自己搞(做一个网络框架并不特别费力),你会发现,复杂的地方不…
shutdown(both)还需要close,不然你就泄漏了一个或几个handle或fd以及相关资源。&br&&br&read返回0表示你收到了对方发来的fin,这可能是对方调用shutdown(send),也可能是对方调用了close()。从tcp协议本身来说,你是无法知道对方到底是调用了close()还是调用了shutdown(send)的,os的tcp协议栈也不知道。因此此时是否要close取决于你的应用。通常来说如果对方调用的是close,那么你也可以close。否则你不能close,例如对方发送一个包给你并shutdown write然后调用recv,这时候你还可以返回一个或多个包,连接此时处于半关闭状态,可以一直持续。这么做的客户端不多(connect, send, shtudown(send), recv();),但的确有,而且是完全合法的。如果通讯双方都是你自己的代码,那么你知道是哪种情况。如果你不能了解对方的代码,甚至你是个proxy,两边代码你都不了解,那么通常来说你不能close。&br&&br&很多server/proxy的实现为当read返回0就close,这种实现是错误的,这个实现无法兼容刚才我说的那种情况。对于proxy来说,正确的做法是透传双方的行为。因此,当你read(client_side_socket)返回0时,你应该对另外一端调用shutdown(server_side_socket, send),这样服务器就会read返回0,你透明的传递了这个行为。那么作为proxy,你什么时候才能close呢?client_socket和server_socket上read都返回了0,或者有任何一方返回了-1时你可以close。当然你也可以考虑设置一个超时时间,如果线路上超过5分钟没有数据你就断开,但这是另一个维度的问题。&br&&br&关于close,要注意的是默认情况下它是一个异步的过程。作为proxy来说,如果你想避免大量close_wait,那么你可以在close之前shutdown,然后启动一个5s的delaytask,在delaytask里设置超时时间为0的so_linger,然后close,对socket进行hard close。这时候close是同步的,如果此时不能优雅关闭,那么系统会立刻强制关闭。&br&&br&我没有看muduo的代码。如果你在2处close同一个socket,这是高危行为。因为2次close之间很可能会有一个新socket产生并且值和你第一次close的那个一样。你第二次close就会错误的close了一个不属于你的socket。这种错误非常难查,因此绝对不要干这种事。
shutdown(both)还需要close,不然你就泄漏了一个或几个handle或fd以及相关资源。 read返回0表示你收到了对方发来的fin,这可能是对方调用shutdown(send),也可能是对方调用了close()。从tcp协议本身来说,你是无法知道对方到底是调用了close()还是调用了shu…
&figure&&img src=&https://pic3.zhimg.com/v2-5bc7fe526d44c4d_b.jpg& data-rawwidth=&994& data-rawheight=&653& class=&origin_image zh-lightbox-thumb& width=&994& data-original=&https://pic3.zhimg.com/v2-5bc7fe526d44c4d_r.jpg&&&/figure&&p&本系列文章主要面向 TiKV 社区开发者,重点介绍 TiKV 的系统架构,源码结构,流程解析。目的是使得开发者阅读之后,能对 TiKV 项目有一个初步了解,更好的参与进入 TiKV 的开发中。&br&需要注意,TiKV 使用 Rust 语言编写,用户需要对 Rust 语言有一个大概的了解。另外,本系列文章并不会涉及到 TiKV 中心控制服务 Placement Driver(PD) 的详细介绍,但是会说明一些重要流程 TiKV 是如何与 PD 交互的。&br&TiKV 是一个分布式的 KV 系统,它采用 Raft 协议保证数据的强一致性,同时使用 MVCC + 2PC 的方式实现了分布式事务的支持。&br&本文为本系列文章第二节。&/p&&h3&Placement Driver&/h3&&p&在继续之前,我们先简单介绍一下 Placement Driver(PD)。PD 是 TiKV 的全局中央控制器,存储整个 TiKV 集群的元数据信息,负责整个 TiKV 集群的调度,全局 ID 的生成,以及全局 TSO 授时等。&/p&&p&PD 是一个非常重要的中心节点,它通过集成 etcd,自动的支持了分布式扩展以及 failover,解决了单点故障问题。关于 PD 的详细介绍,后续我们会新开一篇文章说明。&/p&&p&在 TiKV 里面,跟 PD 的交互是放在源码的 pd 目录下,现在跟 PD 的交互都是通过自己定义的 RPC 实现,协议非常简单,在 pd/mod.rs 里面我们直接提供了用于跟 PD 进行交互的 Client trait,以及实现了 RPC Client。&/p&&p&PD 的 Client trait 非常简单,多数都是对集群元信息的 set/get 操作,需要额外注意的几个:&/p&&p&bootstrap_cluster:当我们启动一个 TiKV 服务的时候,首先需要通过 is_cluster_bootstrapped 来判断整个 TiKV 集群是否已经初始化,如果还没有初始化,我们就会在该 TiKV 服务上面创建第一个 region。&/p&&p&region_heartbeat:定期 Region 向 PD 汇报自己的相关信息,供 PD 做后续的调度。譬如,如果一个 Region 给 PD 上报的 peers 的数量小于预设的副本数,那么 PD 就会给这个 Region 添加一个新的副本 Peer。&/p&&p&store_heartbeat:定期 store 向 PD 汇报自己的相关信息,供 PD 做后续调度。譬如,Store 会告诉 PD 当前的磁盘大小,以及剩余空间,如果 PD 发现空间不够了,就不会考虑将其他的 Peer 迁移到这个 Store 上面。&/p&&p&ask_split/report_split:当 Region 发现自己需要 split 的时候,就 ask_split 告诉 PD,PD 会生成新分裂 Region 的 ID ,当 Region 分裂成功之后,会 report_split 通知 PD。&/p&&p&注意,后面我们会让 PD 支持 gRPC 协议,所以 Client API 到时候可能会有变更。&/p&&h3&Raftstore&/h3&&p&因为 TiKV 目标是支持 100 TB+ 以上的数据,一个 Raft 集群是铁定没法支持这么多数据的,所以我们需要使用多个 Raft 集群,也就是 Multi Raft。在 TiKV 里面,Multi Raft 的实现是在 Raftstore 完成的,代码在 raftstore/store 目录。&/p&&h4&Region&/h4&&p&因为我们要支持 Multi Raft,所以我们需要将数据进行分片处理,让每个 Raft 单独负责一部分数据。&/p&&p&通常的数据分片算法就是 Hash 和 Range,TiKV 使用的 Range 来对数据进行数据分片。为什么使用 Range,主要原因是能更好的将相同前缀的 key 聚合在一起,便于 scan 等操作,这个 Hash 是没法支持的,当然,在 split/merge 上面 Range 也比 Hash 好处理很多,很多时候只会涉及到元信息的修改,都不用大范围的挪动数据。&/p&&p&当然,Range 有一个问题在于很有可能某一个 Region 会因为频繁的操作成为性能热点,当然也有一些优化的方式,譬如通过 PD 将这些 Region 调度到更好的机器上面,提供 Follower 分担读压力等。&/p&&p&总之,在 TiKV 里面,我们使用 Range 来对数据进行切分,将其分成一个一个的 Raft Group,每一个 Raft Group,我们使用 Region 来表示。&/p&&p&Region 的 protobuf 协议定义如下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&message Region {
optional uint64 id
= 1 [(gogoproto.nullable) = false];
optional bytes
optional bytes
optional RegionEpoch region_epoch
repeated Peer
message RegionEpoch {
optional uint64 conf_ver
= 1 [(gogoproto.nullable) = false];
optional uint64 version
= 2 [(gogoproto.nullable) = false];
message Peer {
optional uint64 id
= 1 [(gogoproto.nullable) = false];
optional uint64 store_id
= 2 [(gogoproto.nullable) = false];
&/code&&/pre&&/div&&p&id:Region 的唯一表示,通过 PD 全局唯一分配。&/p&&p&start_key, end_key:用来表示这个 Region 的范围 [start_key, end_key),对于最开始的 region,start 和 end key 都是空,TiKV 内部会特殊处理。&/p&&p&region_epoch:当一个 Region 添加或者删除 Peer,或者 split 等,我们就会认为这个 Region 的 epoch 发生的变化,RegionEpoch 的 conf_ver 会在每次做 ConfChange 的时候递增,而 version 则是会在每次做 split/merge 的时候递增。&/p&&p&peers:当前 Region 包含的节点信息。对于一个 Raft Group,我们通常有三个副本,每个副本我们使用 Peer 来表示,Peer 的 id 也是全局由 PD 分配,而 store_id 则表明这个 Peer 在哪一个 Store 上面。&/p&&h4&RocksDB / Keys Prefix&/h4&&p&对于实际数据存储,无论是 Raft Meta,Log,还是 State Machine 的 data,我们都存到一个 RocksDB 实例里面。关于 RocksDB,可以详细参考 &a href=&https://link.zhihu.com/?target=https%3A//github.com/facebook/rocksdb& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&facebook/rocksdb&/a&。&/p&&p&我们使用不同的前缀来对 Raft 以及 State Machine 等数据进行区分,具体可以参考 raftstore/store/keys.rs,对于 State Machine 实际的 data 数据,我们统一添加 ‘z’ 前缀。而对于其他会存在本地的元数据(包括 Raft),我们统一添加 0x01 前缀。&/p&&p&这里简单说明一下一些重要元数据的 Key 格式,我们忽略最开始的 0x01 前缀。&/p&&ul&&li&&p&0x01:用于存放StoreIdent,在初始化这个 Store 的时候,我们会将 Store 的 Cluster ID,Store ID 等信息存储到这个 key 里面。&/p&&/li&&li&&p&0x02:用来存储 Raft 一些信息,0x02 之后会紧跟该 Raft Region 的 ID(8字节大端序 ),然后在紧跟一个 Suffix 来标识不同的子类型:&/p&&ul&&li&&p&0x01:用于存放 Raft Log,后面紧跟 Log Index(8字节大端序)&/p&&/li&&li&&p&0x02:用于存放 RaftLocalState&/p&&/li&&li&&p&0x03:用于存放 RaftApplyState&/p&&/li&&/ul&&/li&&li&&p&0x03:用来存储 Region 本地的一些元信息,0x03 之后紧跟 Raft Region ID,随后在紧跟一个 Suffix 来表示不同的子类型:&/p&&ul&&li&&p&0x01:用于存放 RegionLocalState&/p&&/li&&/ul&&/li&&/ul&&p&对于上面提到的几个类型,都在 protobuf 里面定义:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&message RaftLocalState {
optional eraftpb.HardState hard_state
optional uint64 last_index
message RaftApplyState {
optional uint64 applied_index
optional RaftTruncatedState truncated_state = 2;
enum PeerState {
message RegionLocalState {
optional PeerState state
optional metapb.Region region
&/code&&/pre&&/div&&p&RaftLocalState: 用于存放当前 Raft 的 HardState 以及最后一个 Log index。&/p&&p&RaftApplyState: 用于存放当前 Raft 最后 apply 的 Log index 以及被 truncated 的 Log 信息。&/p&&p&RegionLocalStaste: 用于存放 Region 信息以及在该 Store 上面对应的 Peer 状态,Normal 表明是一个正常的 Peer,Applying 表明该 Peer 还没做完 apply snapshot 的操作,而 Tombstone 则表明该 Peer 已经被移除出了 Region,不能在参与到 Raft Group 里面。&/p&&h4&Peer Storage&/h4&&p&前面已经知道,我们通过 RawNode 来使用 Raft。因为一个 Region 对应的一个 Raft Group,Region 里面的 Peer 就对应的是一个 Raft 副本。所以,我们在 Peer 里面封装了对 RawNode 的操作。&/p&&p&要使用 Raft,我们需要定义自己的 Storage,这在 raftstore/store/peer_storage.rs 的 PeerStorage 类里面实现。&/p&&p&当创建 PeerStorage 的时候,首先我们会从 RocksDB 里面得到该 Peer 之前的 RaftLocalState,RaftApplyState,以及 last_term 等,这些会缓存到内存里面,便于后续的快速度访问。&/p&&p&PeerStorage 需要注意几个地方:&/p&&p&首先就是 RAFT_INIT_LOG_TERM 和 RAFT_INIT_LOG_INDEX,它们的值都是 5(只要大于 1 都可以)。在 TiKV 里面,一个 Peer 的创建有如下几种方式:&/p&&ol&&li&&p&主动创建,通常对于第一个 Region 的第一个副本 Peer,我们采用这样的创建方式,初始化的时候,我们会将它的 Log Term 和 Index 设置为 5。&/p&&/li&&li&&p&被动创建,当一个 Region 添加一个副本 Peer 的时候,当这个 ConfChange 命令被 applied 之后, Leader 会给这个新增 Peer 所在的 Store 发送 Message,Store 收到这个 Message 之后,发现并没有相应的 Peer 存在,并且确定这个 Message 是合法的,就会创建一个对应的 Peer,但此时这个 Peer 是一个未初始化的 Peer,不知道所在的 Region 任何的信息,我们使用 0 来初始化它的 Log Term 和 Index。Leader 就能知道这个 Follower 并没有数据(0 到 5 之间存在 Log 缺口),Leader 就会给这个 Follower 直接发送 snapshot。&/p&&/li&&li&&p&Split 创建,当一个 Region 分裂成两个 Region,其中一个 Region 会继承分裂之前 Region 的元信息,只是会将自己的 Range 范围修改。而另一个 Region 相关的元信息,则会新建,新建的这个 Region 对应的 Peer,初始的 Log Term 和 Index 也是 5,因为这时候 Leader 和 Follower 都有最新的数据,不需要 snapshot。(注意:实际 Split 的情况非常的复杂,有可能也会出现发送 snapshot 的情况,但这里不做过多说明)。&/p&&/li&&/ol&&p&然后就是需要注意 snapshot 的处理。无论 generate 还是 apply snapshot,都是一件比较费时的操作,为了不让 snapshot 的处理卡主整个 Raft 线程,PeerStore 都是会先只同步更新 snapshot 相关的元信息,这样就不用阻碍后续的 Raft 流程,然后会在另一个线程异步的进行 snapshot 的操作。PeerStorage 会维护一个 snapshot 的 state,如下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&pub enum SnapState {
Generating(Receiver&Snapshot&),
Applying(Arc&AtomicUsize&),
ApplyAborted,
&/code&&/pre&&/div&&p&这里注意 Generating 是一个 channel Receiver,当异步 snapshot 生成好之后,就会给这个 channel 发送消息,这样下一次 Raft 检查的时候,就能直接从这个 channel 得到 snapshot 了。Applying 是一个共享的原子整数,这样就能多线程去判断当前 applying 的状态,包括:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&pub const JOB_STATUS_PENDING: usize = 0;
pub const JOB_STATUS_RUNNING: usize = 1;
pub const JOB_STATUS_CANCELLING: usize = 2;
pub const JOB_STATUS_CANCELLED: usize = 3;
pub const JOB_STATUS_FINISHED: usize = 4;
pub const JOB_STATUS_FAILED: usize = 5;
&/code&&/pre&&/div&&p&譬如,如果状态是 JOB_STATUS_RUNNING,那么表明当前正在进行 applying snapshot 的操作。现阶段,我们是不允许 FAILED 的,也就是如果 apply snapshot 失败,我们会 panic。&/p&&h4&Peer&/h4&&p&Peer 封装了 Raft RawNode,我们对 Raft 的 Propose,ready 的处理都是在 Peer 里面完成的。&/p&&p&首先关注 propose 函数,Peer 的 propose 是外部 Client command 的入口。Peer 会判断这个 command 的类型:&/p&&ul&&li&&p&如果是只读操作,并且 Leader 仍然是在 lease 有效期内,Leader 就能直接提供 local read,不需要走 Raft 流程。&/p&&/li&&li&&p&如果是 Transfer Leader 操作,Peer 首先会判断自己还是不是 Leader,同时判断需要变成新 Leader 的 Follower 是不是有足够新的 Log,如果条件都满足,Peer 就会调用 RawNode 的 transfer_leader 命令。&/p&&/li&&li&&p&如果是 Change Peer 操作,Peer 就会调用 RawNode propose_conf_change。&/p&&/li&&li&&p&剩下的,Peer 会直接调用 RawNode 的 propose。&/p&&/li&&/ul&&p&在 propose 之前,Peer 也会将这个 command 对应的 callback 存到 PendingCmd 里面,当对应的 log 被 applied 之后,会通过 command 里面唯一的 uuid 找到对应的 callback 调用,并给 Client 返回相应的结果。&/p&&p&另一个需要关注的就是 Peer 的 handle_raft_ready 系列函数,在之前 Raft 章节里面介绍过,当一个 RawNode ready 之后,我们需要对 ready 里面的数据做一系列处理,包括将 entries 写入 Storage,发送 messages,apply committed_entries 以及 advance 等。这些全都在 Peer 的 handle_raft_ready 系列函数里面完成。&/p&&p&对于 committed_entries 的处理,Peer 会解析实际的 command,调用对应的处理流程,执行对应的函数,譬如 exec_admin_cmd 就执行 ConfChange,Split 等 admin 命令,而 exec_write_cmd 则执行通常的对 State Machine 的数据操作命令。为了保证数据的一致性,Peer 在 execute 的时候,都只会将修改的数据保存到 RocksDB 的 WriteBatch 里面,然后在最后原子的写入到 RocksDB,写入成功之后,才修改对应的内存元信息。如果写入失败,我们会直接 panic,保证数据的完整性。&/p&&p&在 Peer 处理 ready 的时候,我们还会传入一个 Transport 对象,用来让 Peer 发送 message,Transport 的 trait 定义如下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&pub trait Transport: Send + Clone {
fn send(&self, msg: RaftMessage) -& Result&()&;
&/code&&/pre&&/div&&p&它就只有一个函数 send,TiKV 实现的 Transport 会将需要 send 的 message 发到 Server 层,由 Server 层发给其他的节点。&/p&&h4&Multi Raft&/h4&&p&Peer 只是单个 Region 的副本,因为 TiKV 是支持 Multi Raft,所以对于一个 Store 来说,我们需要管理多个 Region 的副本,这些都是在 Store 类里面统一进行管理的。&/p&&p&Store 会保存所有的 Peers 信息,使用:region_peers: HashMap&u64, Peer&&/p&&p&region_peers 的 key 就是 Region ID,而 Peer 则是该 Region 在该 Store 上面的副本 Peer。&/p&&p&Store 使用 &a href=&https://link.zhihu.com/?target=https%3A//github.com/carllerche/mio& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&mio&/a& 驱动整个流程(后续我们会使用 &a href=&https://link.zhihu.com/?target=https%3A//github.com/tokio-rs/tokio-core& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&tokio-core&/a& 来简化异步逻辑处理)。&/p&&p&我们在 mio 里面注册一个 base Raft Tick,每隔 100ms,调用一次,Store 会遍历所有的 Peer,一次调用对应的 RawNode tick 函数,驱动 Raft。&/p&&p&Store 通过 mio 的 notify 机制,接受外面 Client 的请求处理,以及其他 Store 发过来的 Raft message。 譬如收到 Msg::RaftCmd 消息之后,Store 就会调用 propose_raft_command 来处理,而收到 Msg::RaftMessage 消息之后,Store 就会调用 on_raft_message 来处理。&/p&&p&在每次 EventLoop 循环的最后,也就是 mio 的 tick 回调里面,Store 会进行 on_raft_ready 的处理:&/p&&ol&&li&&p&Store 会遍历所有的 ready Peers,调用 handle_raft_ready_append,我们会使用一个 WriteBatch 来处理所有的 ready append 数据,同时保存相关的结果。&/p&&/li&&li&&p&如果 WriteBatch 成功,会依次调用 post_raft_ready_append,这里主要用来处理Follower 的消息发送(Leader 的消息已经在 handle_raft_ready_append 里面完成)。&/p&&/li&&li&&p&然后,Store 会依次调用 handle_raft_ready_apply,apply 相关 committed entries,然后调用 on_ready_result 处理最后的结果。&/p&&/li&&/ol&&h3&Server&/h3&&p&Server 层就是 TiKV 的网络层,现阶段,TiKV 使用 mio 来实现整个网络的处理,而网络协议则是使用自定义的,如下:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&message = header + body
| 0xdaf4(2 bytes magic value) | 0x01(version 2 bytes) | msg_len(4 bytes) | msg_id(8 bytes) |
&/code&&/pre&&/div&&p&任何一个 message,我们都使用 header + body 的方式,body 就是实际的 message 数据,使用 protobuf 编码,而 header,首先就是两个字节的 magic value,0xdaf4,然后就是版本号,再就是 message 的整个长度,以及 message 的唯一 ID。&/p&&p&对于 mio,在 Linux 下面就是封装的 epoll,所以熟悉 epoll 的用户应该能非常方便的使用 mio 进行网络开发,简单流程如下:&/p&&ul&&li&&p&bind 一个端口,生成一个 TcpListener 对象,并且 register 到 mio。&/p&&/li&&li&&p&处理 TcpListener on_readable 的回调,调用 accept 函数得到生成的 socket TcpStream,register 到 mio,我们后续就用这个 TcpStream 跟客户端进行交互。&/p&&/li&&li&&p&TcpStream 处理 on_readable 或者 on_writable 的回调。&/p&&/li&&/ul&&p&同时,Server 通过 mio 的 notify 来接受外面发过来的消息,譬如 TiKV 实现的 Transport,就是 Peer 在调用 send 的时候,将这个 message 直接通过 channel 发给 Server,然后在 notify 里面处理,找到对应的 Store connection,再发送给远端的 Store 的。&/p&&p&对于 snapshot 的发送,Server 会单独新开一个连接,直接使用一个线程同步发送,这样代码逻辑就会简单很多,不需要处理过多的异步 IO 逻辑。而对于接收端来说,在收到一个 message 的时候,会首先看这个 message 的类型,如果发现是 snapshot 的,则会进入接受 snapshot 的流程,会将收到的数据直接发给 snapshot 相关的线程,写到对应的 snapshot 文件里面。如果是其他的 message,也会直接 dispatch 到对应的处理逻辑处理,可以参考 Server 的 on_conn_msg 函数。&/p&&p&因为 Server 就是对网络 IO 的处理,逻辑比较简单,这里就不过多说明,但是,鉴于现阶段 TiKV 使用的是自定义的网络协议,并不利于跟外部其他客户端的对接,并且也没有 pipeline,stream 等优秀特性的 支持,所以后续我们会换成 gRPC。&/p&&h3&总结&/h3&&p&这里,我们解释了 TiKV 核心的 Raft 库,Multi Raft。在后续的章节,我们会介绍 Transaction,Coprocessor 以及 PD 是如何对整个集群进行变更的。(第二部分完结)&/p&
本系列文章主要面向 TiKV 社区开发者,重点介绍 TiKV 的系统架构,源码结构,流程解析。目的是使得开发者阅读之后,能对 TiKV 项目有一个初步了解,更好的参与进入 TiKV 的开发中。 需要注意,TiKV 使用 Rust 语言编写,用户需要对 Rust 语言有一个大概的了…
&figure&&img src=&https://pic4.zhimg.com/v2-edae8d1d1ba56_b.jpg& data-rawwidth=&1280& data-rawheight=&605& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic4.zhimg.com/v2-edae8d1d1ba56_r.jpg&&&/figure&&p&电子游戏中,子弹一经发射,就会在有效射程内作用于其运行轨迹上的单位。判定子弹是否能命中单位,只需看子弹和单位的碰撞体是否会在某个时刻处于重叠位置。&/p&&p&这是容易理解的,在单机游戏中也是容易实现的。但在联网游戏中,由于网络时延的存在,子弹的命中判定则要复杂很多。&/p&&h2&子弹命中单位的基本判定方法&/h2&&p&一个子弹有如下主要组成部分:&/p&&p&1)飞行控制逻辑。飞行控制逻辑用于随时间推移,计算和更新子弹的位置,最终得到一条飞行轨迹。&/p&&p&2)命中判定。子弹的命中,则是指子弹飞行过程中会碰撞每一个处于飞行轨迹上的单位,并产生作用效果。子弹和单位是否碰撞,要看子弹作用半径和单位形状,在逻辑上,又被称为子弹碰撞体和单位碰撞体。&/p&&p&3)效果。在现实世界中子弹的命中效果往往是穿透。在游戏世界中,子弹命中效果可以是穿透,也可以是直接产生AOE,改变飞行轨迹,甚至弹射等等。&/p&&p&为了性能,游戏逻辑往往是离散的。这意味着,子弹的命中判定时机是离散的。如果子弹判定时仅仅使用判定时子弹和单位的空间位置,那么一定会漏判中间某些时刻的命中。虽然Frame1和Frame2时刻,子弹和单位都没有位置重叠,但是中间某个时刻却有可能发生碰撞。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-cd89f8f5cac_b.jpg& data-rawwidth=&528& data-rawheight=&424& class=&origin_image zh-lightbox-thumb& width=&528& data-original=&https://pic1.zhimg.com/v2-cd89f8f5cac_r.jpg&&&figcaption&离散的运算时机对子弹和单位碰撞判定的影响&/figcaption&&/figure&&p&所以计算子弹和单位是否命中时,需要考虑子弹和单位扫过的轨迹。严格的说,子弹和单位的运行轨迹不可能总是沿着直线,即使是相邻的两帧之内,运行方向也可能在时刻变化。要想得到命中的准确判定,有两种方法。一种是得到子弹和单位各自运行轨迹的解析表达式,用解析的方法计算中间时刻是否可能命中。另一种是在中间插值,在更细的粒度上做命中判定。&/p&&p&但是这两种方法都很麻烦,在场景中有数百颗子弹的情况下,计算量也很大。实践中通常采用一些方法去简化和近似。&/p&&p&1)如果帧间隔足够短,那么可以认为两相邻帧之间的运行轨迹是一条直线。&/p&&p&2)通常情况下子弹的飞行速度很快,而单位的移动速度很慢。所以计算命中时采用单位在当前帧的位置与子弹在上一帧内扫过的轨迹求交,通常就可以达到比较好的结果。&/p&&p&3)帧间隔较小的情况下,子弹在上一帧内扫过的轨迹与单位在上一帧内扫过的轨迹只要有重叠,就可以认为命中。那种由于飞行速度和初始位置差异导致先后掠过同一位置却未碰撞的情况非常少见。而且由于子弹和单位都有碰撞体积,这种误差通常是用户可以接受的。&/p&&h2&网游环境下子弹和单位碰撞需要额外考虑的问题&/h2&&p&同步会给网游环境下子弹和单位碰撞的判定带来额外复杂度。在一个简单的C/S同步环境下,所有单位和子弹的运算都是服务端优先算,计算结果再同步到客户端。客户端的模拟总是延后于服务端的,是服务端的简单重放。这种情况下,命中判定的方法和单机环境下并没有本质不同。DOTA2等游戏采用这种方法。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-5e4b1bc41_b.jpg& data-rawwidth=&716& data-rawheight=&357& class=&origin_image zh-lightbox-thumb& width=&716& data-original=&https://pic2.zhimg.com/v2-5e4b1bc41_r.jpg&&&figcaption&服务端先于客户端,客户端是服务端的重放&/figcaption&&/figure&&p&服务端领先于客户端的坏处是,玩家的输入必须等待一个RTT才会有反馈,虽然公平但体验不好。有一些游戏在客户端向服务端同步输入后,立刻播放相应的动作,可以给玩家即时反馈。这种反馈不会做位置和朝向的预计算,效果也不够好。&/p&&p&最好的方法是玩家的位置在客户端做预计算,这也是守望先锋和暗黑3的做法。这种情况下,对于玩家单位来说,客户端比服务端要先算。其他单位还是服务端先算。如果子弹也是服务端先算,上述的命中判定就会有额外的误差。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-652d45d3cb2b6d5caf22_b.jpg& data-rawwidth=&769& data-rawheight=&383& class=&origin_image zh-lightbox-thumb& width=&769& data-original=&https://pic3.zhimg.com/v2-652d45d3cb2b6d5caf22_r.jpg&&&figcaption&玩家采用客户端先算,子弹采用服务端先算&/figcaption&&/figure&&p&对于玩家来说,子弹的位置需要经过RTT/2才会同步到客户端,玩家的输入需要RTT/2才会同步到服务端。玩家在客户端看到的子弹和玩家单位的位置关系是(x1,y1),而服务端实际计算命中时子弹和玩家的位置关系是(x2,y1),这两者是有可能不一致的。也就是说,服务端如果采用(x2,y1)计算命中,就会导致在客户端,看起来命中了实际判定却未命中,或者玩家做了个闪避动作,看起来躲开了子弹,但是服务端仍然判定命中。这样的命中判定结果在服务器看来并没有错,但是玩家体验不好。&/p&&p&要解决这个问题也很简单。玩家在客户端看到的子弹和玩家的位置关系是(x1,y1),只要在服务端也采用(x1,y1)计算命中就可以。也就是说,服务端计算命中时,需要将子弹位置回滚RTT时间。&/p&&h2&子弹同步的两种方式&/h2&&p&刚才说了玩家位置同步的两种方式,即,服务端先于客户端,或客户端先于服务端。对于子弹来说,除了服务端先于客户端算,也可以采用客户端先行模拟的方式。守望先锋就是这种做法。如果玩家单位和子弹都采用客户端先于服务端计算的方法,服务端计算命中时也不需要将子弹位置回滚。&/p&&p&游戏中,一定还存在必须采用服务端先于客户端计算的单位,比如NPC等。子弹若在客户端先行,如果要计算子弹和NPC的命中关系,还是要考虑同步因素的影响。&/p&&p&客户端先行模拟子弹有局限性。客户端通常并没有足够的信息判断是否生成某颗子弹,这时就必须在服务端先于客户端模拟。若子弹在飞行过程中会改变轨迹和形态,服务端处理起来会更方便。此外,客户端先行,服务端就必须做严密的防外挂处理。&/p&&h2&子弹和玩家单位命中判定的设计取舍&/h2&&p&刚才讲到,玩家单位在客户端先行模拟,子弹由服务端先行模拟,子弹和玩家单位命中判定时应该用玩家单位当前位置和子弹一个RTT之前的位置计算。&/p&&p&但是这个设计带来的问题是子弹和玩家单位的碰撞,在其他玩家看来是不准确的。因为客户端看到的子弹的位置和其他玩家的位置都是服务端同步过来的,如果客户端要看到准确的命中结果,那么在服务端,子弹就应该用其当前的位置与其他玩家的当前位置计算碰撞。&/p&&p&其结果就是,如果玩家和子弹的当前位置做碰撞计算,那么客户端看到的子弹和其他玩家的碰撞是和视觉吻合的。但是自己和子弹的命中判定看起来不准确。&/p&&p&如果玩家和子弹历史位置计算碰撞,那么客户端看到的子弹和自己的碰撞是吻合的,和其他玩家的碰撞看起来却是不准确的。&/p&&p&采用哪种策略,就看游戏设计者如何根据实际情况做取舍了。&/p&&p&&/p&
电子游戏中,子弹一经发射,就会在有效射程内作用于其运行轨迹上的单位。判定子弹是否能命中单位,只需看子弹和单位的碰撞体是否会在某个时刻处于重叠位置。这是容易理解的,在单机游戏中也是容易实现的。但在联网游戏中,由于网络时延的存在,子弹的命中判…
中国科大 LUG 的 &a data-hash=&f2efaaed2de8d50eee749a& href=&//www.zhihu.com/people/f2efaaed2de8d50eee749a& class=&member_mention& data-editable=&true& data-title=&@高一凡& data-hovercard=&p$b$f2efaaed2de8d50eee749a&&@高一凡&/a& 在 LUG HTTP 代理服务器上部署了 Linux 4.9 的 TCP BBR 拥塞控制算法。从科大的移动出口到新加坡 DigitalOcean 的实测下载速度&b&从 647 KB/s 提高到了 22.1 MB/s&/b&(截屏如下)。&br&&figure&&img src=&https://pic4.zhimg.com/50/v2-2218943eab7a6b70ad0f4a213cb1f393_b.jpg& data-rawwidth=&840& data-rawheight=&167& class=&origin_image zh-lightbox-thumb& width=&840& data-original=&https://pic4.zhimg.com/50/v2-2218943eab7a6b70ad0f4a213cb1f393_r.jpg&&&/figure&(应评论区各位 dalao 要求,补充测试环境说明:是在新加坡的服务器上设置了 BBR,&b&新加坡的服务器是数据的发送方&/b&。这个服务器是访问墙外资源的 HTTP 代理。科大移动出口到 DigitalOcean 之间不是 dedicated 的专线,是走的公网,科大移动出口这边是 1 Gbps 无限速(但是要跟其他人 share),DigitalOcean 实测是限速 200 Mbps。RTT 是 66 ms。实测结果这么好,也是因为大多数人用的是 TCP Cubic (Linux) / Compoun}

我要回帖

更多关于 测试丢包软件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信