Jan 8, 2025
8 mins read
TCP重传机制
正常发包1,2,3,4,5,6,7,8,收包都会带一个ACK序号,收包1,2,3,4,5,6,7,8
如果5号包丢了的话,那么收到的就是1,2,3,4,4,4,4,4
Question:什么时候使用TCP / UDP?
Answer:对于实时性要求不高的游戏会采用TCP协议 - 炉石传说
需要低延迟的游戏会采用UDP协议 - CSGO
但是登陆验证、商城等数据会使用TCP协议,因为对数据的可靠性要求高。
现在很多游戏不会直接使用原生的UDP,因为UDP本身并不可靠、数据的到达顺序也是混乱的,如说喝了一瓶药恢复魔法值再释放一个技能结果变成了释放了技能却没有魔法值之后再喝了药,因此通常会在UDP上进行优化增加类似于TCP的可靠性。
自动重传请求机制ARQ:是基于ACK的错误控制方法,发送端会等待接收端的ACK,如果确认未到达或收到的是错误反馈,发送端会自动重传未正确到达的数据。
滑窗协议是经典的ARQ实现方法
Stop-and-Wait ARQ
发送端发送一个数据包,等待接收端的确认(ACK)。如果超时未收到 ACK,重新发送数据包。
特点:实现简单,但效率低(管道中只能同时传输一个包)。
Go-Back-N ARQ
发送端可以连续发送多个数据包,而无需等待每个包的确认。
如果一个包出错,接收端会丢弃当前包和其后的所有包,发送端需要重发从出错包开始的所有数据包。
特点:提高了管道利用率,但重传开销大。
Selective Repeat ARQ
发送端可以连续发送多个数据包,接收端仅请求重传错误的包。
特点:管道利用率高,重传开销小,但实现复杂。
异或校验位
Reed-Solomon codes
由于网络通信延迟的存在,客户端向服务器端发送一个包后都需要等待一定的时间才能收到回包,这个间隔的时间称为round-trip time(RTT)。
NTP:为了尽可能精准地将客户端的时间与时间服务器同步。
NTP消息中包含4个关键时间戳:
偏移量如图所示
客户端时间正确是17:01:35,客户端接收后增加偏移量。
尽管利用socket我们可以实现客户端和服务器的通信,但对于网络游戏来说完全基于socket的通信非常复杂。这主要是因为网络游戏中客户端需要向服务器发送大量不同类型的消息,同时客户端也需要解析相应类型的反馈,这就会导致游戏逻辑变得无比复杂。
因此在现代网络游戏中一般会使用RPC的方式来实现客户端和服务器的通信。基于RPC的技术在客户端可以像本地调用函数的方式来向服务器发送请求,这样使得开发人员可以专注于游戏逻辑而不是具体底层的实现。
在RPC中会大量使用**IDL(interface definiton language)**来定义不同的消息形式。
syntax = "proto3";
service UserService {
// 定义一个方法 GetUser
rpc GetUser(GetUserRequest) returns (GetUserResponse);
}
message GetUserRequest {
int32 id = 1; // 用户 ID
}
message GetUserResponse {
string name = 1; // 用户名
int32 age = 2; // 用户年龄
}
Sharing is caring!