在开发完ue的demo后,回头总结了一些心得,趁着闲暇就记录下来。
这一篇看上去一点也不ue4,等熟了ue4的网络同步再来补相关部分。
TCP三四次握手
创建连接(三次握手)
第一次:客户端尝试连接服务器,向服务器发送syn包(seq=x)。客户端进入SYN_SEND状态。
第二次:服务器接收客户端的syn包,同时向客户端发送一个SYN包(seq=y,ack=x+1),同时发送一个ACK,即发送的是ACK+SYN,服务器进入SYN_RECV状态
第三次:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(seq=x+1,ack=y+1),客户端和服务器进入Establish,TCP连接建立完成。
释放连接(四次握手)
第一次:客户端进程发出连接释放报文FIN,并停止发送数据。客户端进入FIN_WAIT1状态。
第二次:服务器收到连接释放报文,发出确认报文ACK(ack=u+1,seq=v),服务器进入CLOSE_WAIT状态。此时客户端不接受数据,但若服务器发送数据,客户端依然要接受。客户端收到服务器的确认请求,进入FIN_WAIT2状态。
第三次:服务器将最后的数据发送完,向客户端发送释放连接报文FIN(ack=u+1,seq=w),服务器进入LAST_ACK状态。
第四次:客户端收到服务器的连接释放报文,必须发出确认报文ACK(ack=w+1,seq=u+1),客户端进入TIME_WAIT状态,等待2xMSL(最长报文寿命时间),进入CLOSED,服务器收到ACK立即进入CLOSED。
一些之外的思考
为什么建立连接是三次握手,释放连接是四次握手?
因为建立连接时服务器收到客户端的SYN时,可以同时发送一个ACK加SYN。释放连接时由于不知道是否还要继续传输文件,SOCKET没有立即关闭,所以只能发送一个ACK。
为什么TIME_WAIT状态需要经过2MSL才能进入CLOSE?
我们得假设网络是不可靠的。TIME_WAIT用来重发可能丢失的ACK。当服务器没有收到ACK时,会一直重复发送FIN,所以服务端不能关闭,得确保在2MSL内没有收到FIN才能进入CLOSED。其中2MSL是一个发送和一个回复所需的最大时间。
为什么两次握手不能完成TCP连接创建?
若只有两次连接,在服务器传回给客户端的应答丢失的情况下,客户端不知道服务器是否准备好,会认为连接未建立而忽略服务器发来的任何分组,只等待ACK。而服务器会重复发送同样的分组,从而造成死锁。
TCP和UDP的区别
- TCP面向连接,UDP无连接
- TCP面向字节流,UDP面向报文
- TCP提供可靠性(按序发送,有序到达,超时重传),UDP只尽力而为,不保证任何事。
- TCP首部20字节,所需资源多,而UDP只占用8字节
- TCP有流量控制和拥塞控制,而UDP没有(拥塞不会影响发送端的发送速率)
- TCP只支持点对点,而UDP可以一对一,一对多,多对多。
网络同步
RPC
即远程过程调用,本地调用远程提供的函数。因为不是一个内存空间,需要网络来表达调用的语义和数据,而不能直接调用。
带来的问题:Call ID映射(让服务器知道我调用是哪个函数),序列化与反序列化(参数需要通过一种标准化的格式来传输,将对象转换为一系列字节流),网络传输
属性同步
对象A的属性更改了,其他端的对应属性也要更改。一般是服务器更改同步到其他客户端。
帧同步
帧同步只同步操作,大部分逻辑在客户端上运行,服务器主要用于验证和广播,逻辑易实现,数据量少,可重播,一致性好。一个玩家卡了所有人都卡。
状态同步
同步游戏的各种状态。客户端上传操作到服务器,服务器收到后运算结果,把各个状态广播给各个客户端,客户端根据状态展现不同的内容。
状态同步是一种不严谨的同步,对延迟的要求并不高。
对比
帧同步客户端一致性全程一致,状态同步中途可能有变化。
延迟方面帧同步要求搞,状态同步要求低。
流量方面,帧同步的流量与操作数量成正比,而状态同步与物体数量成正比。
服务器的任务上来看,帧同步服务器做的是同步操作,而状态同步的服务器则需要接受输入,进行全局仿真,状态的复制。
客户端的任务上来看,帧同步客户端做的是全局仿真,而状态同步客户端则是做局部游戏世界的展示。
断线重连,状态同步更容易,帧同步要从头开始运行(王者荣耀)。
开发效率上来看,帧同步的开发效率很高,接近单机开发。状态同步需要前后台联合开发。
安全性来看,帧同步安全性低。而状态同步在服务器端安全性高,但客户端有作弊可能。
修复延迟
插值,预测,缓存,延迟补偿
UE4网络同步架构
以CS模型为基础,做了面向对象风格的封装,网络代码和游戏逻辑完全分离,网络同步支持可视化编程,使用UDP协议通信。
为什么使用纯UDP?‘
TCP的可靠性无法定制,且游戏中许多数据不要求可靠。
TCP与UDP都是基于IP协议,底层会互相干扰,混用也会增加设计复杂度。