游戏服务器需要关注的网络参数介绍

SO_REUSEADDR

这个选项用来设置socket断开之后,是否允许立刻复用之前的地址。

当TCP连接关闭的时候,主动关闭连接的一方会进入TIME_WAIT状态。在这种状态下,该连接的端口无法被复用。TIME_WAIT状态会持续2MSL(Maximun Segment Lifetime),一般为4分钟。

通常我们希望游服重启之后能够立刻绑定之前的端口,因此会设置为true。

SO_BACKLOG

这个选项用来设置连接队列的大小。

客户端向服务器发送的TCP连接请求会被放入到连接队列中,服务器会通过accept()方法从队列中取出请求并进行处理。当连接队列满的时候,新来的连接请求就会被操作系统丢弃掉。

连接队列的大小不能太大,也不能太小。队列过小的话,当服务器接收到大量的连接请求,队列很快就会满,导致很多连接请求被丢弃掉了;队列也不能过大,这会占用不必要的系统内存,而且过大的队列会导致TCP连接请求的平均处理时间过大,从而可能会出现队列中存在过多的失效连接请求。对于失效的连接请求,客户端可能会触发重连机制,这样会浪费服务器的性能。

TCP_NODELAY

这个选项表示是否禁用Nagle算法。

Nagle算法是用来提升TCP协议传输效率的算法。通过将多个小的报文合并成一个大的报文再发送,从而提交传输效率,但是这也会相应的增加协议的延时。

对于游戏这种对数据实时性要求比较高的应用来说,会禁用Nagle算法从而提高数据的实时性。

SO_KEEPALIVE

这个选项表示是否开启TCP连接存活检测。

它的运行机制如下:

  1. 如果通信双方超过两个小时没有数据交换,那么开启SO_KEEPALIVE的一方会发送一个keep-alive包给对方。
  2. 如果对方返回ack,那么表示连接正常,本方会间隔两小时再发送keep-alive包。
  3. 如果对方返回rst,那么表示对方程序已在崩溃后重启,这时本方也应该关闭连接。
  4. 如果对方一直没有回应,本方会间隔75秒重新发送keep-alive包,循环发送直至次数上限,最后关闭连接。

SO_KEEPALIVE的意义是维持长连接不断开,减少重复创建连接带来的开销。它的缺点是keep-alive包发送的间隔时间过长。在实际的游戏服务器中,很难想象会存在长达两小时的时间没有数据通信。因此,在游戏服务器开发中,一般会选择自己实现应用层的心跳包机制,使用更短的心跳包间隔,从而更好的检测连接是否可用以及玩家的在线情况。

这个选项的开启对于游戏服务器来说是可选的。

SO_TIMEOUT

这个选项的作用是设置socket阻塞操作的超时时间。

阻塞操作包括accept、read和UDP的receive。其中影响最大的是read操作。在游戏服务器中,典型的应用场景是先发送消息后接收回包,存在于客户端与服务器、服务器与服务器之间。在这些场合使用阻塞读时需要设置超时时间。

若不设置超时时间,SO_TIMEOUT会取系统默认的超时时间0,即没有超时时间。这样有可能会永久阻塞进行IO操作的线程。因此,在任何时候都应该为阻塞操作设置一个超时时间。

CONNECT_TIMEOUT_MILLIS

这个选项是设置TCP连接请求的超时时间。

这个时间是从客户端发起TCP连接请求到服务器成功建立TCP连接的最大超时时间,若超出这个时间,那么操作系统就会认为这个TCP连接请求超时不进行处理。

参考

游戏服务器开发指南(一):设置合适的Socket选项 - 知乎 (zhihu.com)

相关推荐
苏三说技术1 小时前
Claude Code从失控到起飞,只用了这些技巧
后端
长栎2 小时前
写 for 循环写了十年,你却从没用过迭代器模式最狠的那一面
后端
LiaCode2 小时前
Redis 在生产项目的使用
前端·后端
用户559822481222 小时前
Docker Compose Down 导致容器数据误删——ext4 日志恢复全记录
后端
LiaCode2 小时前
一天学完 redis 的爽翻版核心知识总结
前端·后端
大刚测试开发实战2 小时前
如何内网穿透访问本地私有化部署的TestHub
前端·后端·github
xiaodaoluanzha3 小时前
迄今為止,最簡單的編程語言 Nolang
前端·后端
Csvn3 小时前
Docker 容器管理入门 — 从镜像到容器编排
后端
用户762352425913 小时前
ShardingJDBC
后端
行者全栈架构师3 小时前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端