TCP和UDP的区别?
- TCP是面向连接的,是可靠的传输。UDP是不面向连接的,是不可靠的传输。
- TCP是以字节流传输的,UDP是以报文为单位传输的。虽然TCP传输的数据没有边界划分,但是数据的到达是有序且可靠的。而UDP虽然包与包之间有明确的界限,但是可能会有种种原因导致丢包或者乱序。
- TCP的首部较长,最小为20字节,传输的时候开销较大,而UDP是固定首部且只有8个字节。再加上UDP是不面向连接的,所以UDP会比TCP更快。
- 所以像实时性比较高的竞技游戏王者荣耀,使用的就是UDP协议,而像是魔兽世界这种MMORPG类型的,使用的是TCP协议(为了确保高延迟状态下游戏仍然能运行)
可靠:可靠指的是接收方从缓存区读出的数据和发送方发送的是完全一致的
为什么说TCP是面向字节流的而UDP是面向报文的?
TCP会有一个”缓存区“,用来存放等待发送的数据,当TCP决定能发送的时候就会把缓存区中的数据发出,同时TCP还会根据网络拥堵状况来决定每个报文段的大小,也就是说它会控制本次发送要从缓存区中取走多少数据。而UDP更像是一个传递者,它从应用层拿到什么数据就会发送什么数据,不进行长度的拆分或者合并(由应用层控制),所以说它是一个包一个包发送的
粘包问题?
UDP不会有粘包问题,只有使用TCP才会遇到。准确的来说粘包并不是TCP的问题,是程序员在接收方解析数据时碰到的难题。
因为TCP决定了每个报文段的大小,也就是说每个报文段里头可能含有多个细小的包,或者说一个完整的包再加上下一个包的一部分信息。无法区分这一串没有边界的数据流信息就是粘包问题。
如何解决粘包问题?
- 一种方法是固定每个包的长度,这样子接收方在接受的时候可以定长扫描。缺点也很明显,如果包的大小参差不齐那么会很影响效率,优点是很简单。
- 另一种办法是在内容中添加一个定长的头部标记。接收方在接受数据的时候会先定长的扫描这个标记,然后就能得到一个包的大小是多少。这个包在同一个报文段内结束也好,延伸到下一个报文段也好,接收方都能很好的识别。然后再扫描下一个头部标记,如此循环
TCP的连接管理是怎么样的?
- 连接建立(三次握手)
- 数据传送(可靠)
- 连接释放(四次挥手)
三次握手是怎样的?
首先客户端会给服务器发送一条连接请求报文,这条报文段不包含应用层传下的数据,这是第一次握手。
然后当服务端接受到客户端的连接请求的时候,会为这个连接分配各种必要的资源,然后回复一个确认报文,也不包含应用层数据,代表同意此次连接,这是第二次握手。
最后当客户端接收到服务端发来的确认报文时,自身会为这次连接也分配各种必要的资源,然后再向服务端发送确认报文,这是确认的确认,这条确认的确认可以携带应用层传下的数据,两者之间的通讯正式开始,这是第三次握手。
为什么是三次握手而不是两次或者四次
由于网络拥塞,连接请求发送方可能会发送多条连接请求,若只是两次握手的话无法区分哪些是过期的请求,这样子会建立起一个”历史连接“,造成双方资源的浪费
三次连接就能解决的问题没有必要使用四次连接
四次挥手是怎样的?
首先主动断开连接方会发送一个连接释放报文(假设是客户端主动请求关闭),然后客户端会停止发送数据,这是第一次挥手。
然后当服务端接收到客户端的释放请求后,会回复一个确认报文,这个时候的连接处于半关闭状态,此时服务端依然能向客户端发送未发完的数据,这是第二次挥手
当服务端的消息全部发送完成后,会再向客户端发送一次连接释放报文,之后服务端也不再发送数据,这是第三次挥手
最后客户端接收到服务端这条连接释放报文后,会回应一个确认报文。然后进入等待状态,若这段时间内服务端无再发送报文过来,那么连接彻底关闭,等待状态的时间为报文寿命的两倍。这是第四次挥手
为什么是四次?
因为当一方主动断开连接时,另一方可能还会有未完成的数据需要发送和处理
各端是如何区分不同的报文的?
TCP首部设有6个控制位,用来区分不同的报文,如确认位ACK,同步位SYN,终止位FIN。
为什么说TCP是可靠的?
- 重传机制
- 流量控制机制
- 拥塞控制机制
首先TCP能够做到数据的有序传输,而且不丢包。为了保证这两点就需要重传机制。首先接收端会根据报文头部中的序列号来判定数据的接受是否是有序的。同时接收端在接受一个序号正确的数据时,会回应一个ACK报文,代表在这之前所有的数据都正确接受了,如果发生了丢包,那么接收端将会发送重复的ACK报文,发送端会根据超时重传或者快速重传机制来重新发送丢失的报文。
流量控制就是发送方动态调整发送速率使接收方来得及接受,具体实现是发送方从接受方发送的ACK确认报文中的RWND窗口字段来动态调整滑动窗口的大小,以此来达到流量控制
拥塞控制首先会有一个ssthresh门限值,在门限值之前滑动窗口的大小指数增长,达到门限值之后进入拥塞避免阶段,窗口加法增长。当遇到拥塞的时候,窗口会立刻置为1,然后将新的门限值设置为遇到拥塞时窗口大小的一半,之后如此反复
为什么TCP传输的时候需要有滑动窗口
滑动窗口太大或太小会怎么样
帧同步与状态同步
https://zhuanlan.zhihu.com/p/36884005
区别
主要区别就是:
帧同步的战斗逻辑是写在客户端的,服务器负责定时转发玩家的操作,下发到各个客户端上,然后再在客户端上进行计算。
状态同步的战斗逻辑是写在服务器上的,服务器根据玩家传来的各种操作信息进行计算,然后讲计算的结果(玩家的位置,血量等信息)下方给客户端,客户端再做一个数据的体现
游戏举例
王者荣耀等MOBA游戏使用的是帧同步,因为地图较小,玩家固定(一局只有十个人)
绝地求生,魔兽世界等FPS,MMORPG游戏使用的是状态同步,因为地图较大,玩家多。且MMORPG中玩家上下线更为频繁,断线重连实现更为简单。并且如果这两种类型的游戏并不能帧同步实现,因为客户端无法承载大量玩家的操作计算
适用场景
帧同步适合单局时间短,玩家数量少且固定,而且要求公平的游戏
状态同步适合玩家多,对安全性要求高,玩家上下线频繁的游戏
其实两者并不是有你没我,有我没你的关系,一个游戏可能两种同步方式都有使用到
优缺点
优缺点主要从这几个点来分析:流量消耗,网络延迟,断线重连,开发效率,打击感,安全性,性能,公平
-
流量消耗:帧同步的游戏由于只需要传递操作序列,所以一局比赛下来流量消耗几乎是固定的,而状态同步的游戏会随着游戏体量的增加,复杂度的上升而导致流量消耗加大。网速较慢的玩家或流量有限的玩家玩状态同步的游戏会比较吃亏?
-
网络延迟:帧同步的游戏如果网络较为较差,用户体验差。状态同步用户体验则不怎么明显?
-
断线重连:帧同步的游戏需要从第一帧开始计算,短线重连时间长(游戏进行的时间越长重连加载的时间越长),而状态同步只需要拉去当前最新的信息即可
-
开发效率:帧同步的开发效率更高,处理完服务器的下发操作序列后,游戏开发起来和单机游戏类似。状态同步开发难度更高,很多时候需要保证服务器与客户端的每一个角色对象的状态之间保持一致,但事实上你很难做到一致?
-
打击感:肯能是因为状态同步每个角色对象的状态之间很难保持一致,所以无法做到完美的打击感?(又比如射击游戏中要产生100个子弹,这又是要想服务器上传大量的信息,增加了消耗,所以FPS游戏的物理模拟等操作都是在客户端上进行的?);而帧同步客户端模拟的是玩家操作序列,和单机游戏一样,能做出很好的打击效果
-
安全性:状态同步游戏的安全性高,因为逻辑计算都是在服务器上运行的,而帧同步的游戏却可以通过修改内存中的数据来实现作弊?。状态同步的游戏比如MMORPG,修改数值对游戏的影响极高,因为游戏机制是一个“世界”而不是一局一局的比赛;相反,帧同步的游戏有作弊的玩家也是影响一局比赛,可通过玩家举报和封禁的方式来治理
-
性能:帧同步的游戏需要在客户端上计算所有玩家的操作,帧同步的游戏不能裁剪(裁剪掉了它要是再出现在玩家中的视野怎么办,重新计算一边帧操作吗,这是不合理的),如果同屏有大量玩家的话,逻辑优化的压力会很大,因为这些实体的操作都需要经过客户端来计算;而状态同步可以通过裁剪的方式,只显示玩家附近的角色,提高性能
-
帧同步由于是接受服务器定时下发的操作帧,所以较为公平,网速特别快的玩家不会提前得到操作(即使到了也得等到服务器的下发频率到才能转发);而状态同步的话,网速快的玩家数据先到达服务器,服务器优先处计算后发送给对应的客户端,相对来说没那么公平(状态同步是服务端状态改变就同步,帧同步是定时下发)