游戏服务器开发指南(一):设置合适的Socket选项

jforgame-socket快速入门 jforgame-socket是一个通用的网络工具,底层对Netty/Mina进行了封装,屏蔽了私有协议栈定制,消息编解码,消息粘包/拆包问题。jforgame-socket传输层使用了TCP协议。可用于任何需要socket通信的应用。例如游戏服务器,聊天服务器等等。 阅读详情

前言

上周写完系列序言,得到不少读者朋友的关注,这也给了我额外的动力。写东西就是这样,都希望获得更多的关注,如果写出来没什么人看,那就无异于闭门造车、自娱自乐。欢迎朋友们在文后留言,我也会根据大家的反馈适时调整写作的内容和方式。

我在这里整理了一个系列目录游戏服务器开发指南(目录),用于分门别类存放文章的链接地址,方便读者快速索引。目录按不同的主题组织,如网络通信、数据存储等,每个主题会包含若干篇文章。个人计划是平均每周写一篇,写作基于平时工作中产生的灵感,因此不一定会按照主题的排列顺序来。

本周先上第一道开胃菜:为游戏服务器设置合适的Socket选项。这是网络通信主题下的第一篇。

适合游戏服务器的Socket选项

Socket是网络通信中对不同进程收发信息的端点的抽象。Socket本身与协议无关,它既可以支持TCP,也可以支持UDP。

Socket选项的设置会影响Socket本身的行为。在游戏服务器编程中,我们需要为常见的Socket选项设置合适的值。设置时应充分考虑游戏服务器的特点,例如开启TCP_NODELAY来保证尽量低的通信延时。如果设置不当或者忘记设置,程序可能会以违反我们预期的方式工作。以下的Java程序显示了对四种常见Socket选项的设置,以及它们在当前操作系统上的默认值:

        try (Socket socket = new Socket()) {
        	// SO_KEEPALIVE 默认为false
        	System.out.println(socket.getKeepAlive());
        	// SO_REUSEADDR 默认为false
        	System.out.println(socket.getReuseAddress());
        	// SO_TIMEOUT 默认为0
        	System.out.println(socket.getSoTimeout());
        	// TCP_NODELAY 默认为false
        	System.out.println(socket.getTcpNoDelay());
        	socket.setKeepAlive(true);
        	socket.setReuseAddress(true);
        	socket.setSoLinger(true, 0);
        	socket.setSoTimeout(2000);
        	socket.setTcpNoDelay(true);
        }

值得注意的是,同一个Socket选项在不同的操作系统上可能会有不同的默认值。因此,如果一个Socket选项是我们关心的,那么应该在使用前显式地为其赋值,从而避免在不同的平台上出现行为差异。

以上四种Socket选项,只有TCP_NODELAY命名以TCP开头,表示TCP专用;其他都以SO开头,表示通用选项,与具体协议无关。以下分别对它们做介绍。

TCP_NODELAY

这个选项的作用是禁用nagle算法。nagle算法的作用是把小包合并成大包,从而提高带宽利用率。

在TCP传输的过程中,如果一个包过小,例如只有1字节,那么单独传输非常不划算,因为还需要给它加上40字节的包头。为了解决这个问题,设计了nagle算法:只有当收到已发出包的ack消息,或者加上新包后缓冲区凑满一个MSS时,才会发送新包;否则,新包会放入缓冲区延迟发送。

nagle算法对提升带宽利用率效果显著,因此系统默认开启。但是它不适合在强调低延时的游戏服务器中使用。以MSS在以太网中的一般长度1460字节为基准,游戏中通常有相当大比例的包是小包,如果每个包都要等待前一个包的ack,或者等待凑满MSS,那么会极大地影响发送效率,造成显著的延迟。特别是在网络状态不佳时,对延迟的影响更加明显。因此,游戏服务器中一般会开启TCP_NODELAY,禁用nagle算法。

在这里插入图片描述

即使开启TCP_NODELAY,我们还是要注意过多小包对网络通信的影响。一种优化思路是在应用层做小包的合并。例如,对于服务器驱动战斗的状态同步,可以将同步频率由每条新战报产生就同步,改为每帧合并后同步一次,由于客户端实际上也是逐帧计算,所以这种改动不会对客户端表现造成任何影响。更多的合并策略会另起文章讲述,在此不再赘述。

SO_KEEPALIVE

这个选项的作用是定时判断连接是否存活。

它的运行机制如下:

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

SO_KEEPALIVE的意义是维持长连接不断开,减少重复创建连接带来的性能开销。它的缺点是发送keep-alive包的间隔时间过长,达两小时。在实际的游戏服务器中,很难想象会有如此长的时间没有通信数据。因此在游戏服务器开发中,一般会选择自己实现应用层的心跳包机制,用更短的心跳包间隔,实现对TCP连接和玩家在线更灵活及时的判定。在这种情况下,SO_KEEPALIVE的开启不是必需的,但是可以考虑开启,作为极限情况下的一种保底。

SO_REUSEADDR

这个选项通常被用来保证服务器重启后绑定的地址可重用。

当TCP连接关闭时,连接可能在关闭后的一段时间内保持TIME_WAIT状态,时间持续2MSL。在此期间,拥有此连接的应用程序无法将Socket重复绑定到该连接对应的地址和端口。

如果开启SO_REUSEADDR,那么即使以前的连接处于TIME_WAIT状态,也可以绑定Socket。游戏服务器一般都希望重启能立即完成,而且地址能重复使用,因此会选择开启这个选项。

需要注意的是,设置SO_REUSEADDR需要在Socket绑定地址之前进行,否则会没有效果。

以下代码展示了SO_REUSEADDR选项的用法:

public class ReuseAddrServer {
    public static void main(String[] args) throws IOException{
        try (ServerSocket ss = new ServerSocket()) {
       		// 在 Linux 和 Mac 下该选项默认值是true
        	System.out.println(ss.getReuseAddress());
        	// 注释掉下面这行,就不会再出现地址已占用报错
        	ss.setReuseAddress(false);
			ss.bind(new InetSocketAddress("127.0.0.1", 1302));
        	while(true){
			    Socket socket = ss.accept();
			}
		}
	}
}

当启动ReuseAddrServer程序后,再使用nc 127.0.0.1 1302模拟客户端连接,然后kill掉ReuseAddrServer程序并重启,这时会报错:

 java.net.BindException: Address already in use (Bind failed)

如果把ss.setReuseAddress(false);这行注释掉,重新尝试,就不会再出现上述报错。注意以上代码需要在Linux或Mac环境下运行,这两个平台下SO_REUSEADDR默认值为true。而在Windows上有所不同,即使没有开启SO_REUSEADDR也能实现绑定地址的重用,因为Windows提供了另一种机制:通过系统设置默认开启“端口重用”功能。

SO_TIMEOUT

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

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

如果不设置超时时间,SO_TIMEOUT会取系统默认的超时时间0,即超时时间无限。这样有可能永久阻塞进行IO操作的线程,造成严重的问题。笔者曾经遇到一个实例,是在生产中使用了某著名的第三方消息推送SDK,该SDK提送了API用于推送消息并接收响应,但是它底层使用的Socket没有设置SO_TIMEOUT,在一次网络出现问题时,造成用于推送消息的线程池中全部线程“假死”。因此,在任何情况下都应该为阻塞操作设置一个超时时间,避免无限等待。

小结

本文总结了游戏服务器中常用的四种Socket选项,平时开发中应该根据游戏服务器的特点进行合理的设置。为了保证服务器低延时和避免IO线程无限阻塞,应该始终开启TCP_NODELAY和SO_TIMEOUT;为了支持服务器快速重启且地址可复用,应该开启SO_REUSEADDR(系统默认开启);在业务层自己实现心跳机制的前提下,SO_KEEPALIVE作为可选项。

游戏服务器源码实战:热血江湖学习项目 NET框架是一种由微软开发的,用于构建和运行Windows应用程序的软件框架。它提供了一个全面的类库,支持多种编程语言,并且内置了对XML和Web服务的支持。.NET框架由公共语言运行时(CLR)和框架类库(FCL)组成。公共语言运行时(CLR): CLR是.NET框架的核心,负责管理和执行程序代码。它为.NET程序提供内存管理、线程管理以及异常处理等服务。框架类库(FCL) 阅读详情

相关推荐

口袋仙侠游戏服务器源码分析与学习指南

在本章中,我们深入探讨了网络协议的基础知识,特别是TCP和UDP在网络游戏中的应用。我们通过代码示例展示了如何在Python中实现这些协议,并讨论了网络安全与加密技术的重要性。此外,我们还分享了网络延迟优化、数据包重传机制、队列管理等实际应用案例,为游戏开发者提供了如何在游戏开发中应用和优化网络协议的实用指导。下一章将详细介绍服务器安全与性能优化,为游戏服务器的稳定运行提供进一步的保障。

weixin_42515842的博客 695

WebSocket在游戏中的应用

WebSocket(Web套接字)是一种在单个TCP连接上全双工通信的协议。它提供了持久性连接,允许客户端和服务器之间进行实时的、双向的通信。与传统的HTTP请求-响应模型不同,WebSocket建立了一个持久的连接,使得服务器可以主动向客户端推送数据,而不需要依赖客户端发起请求。这种实时通信的能力使得WebSocket非常适合于需要大量实时数据交换的应用,例如聊天、实时游戏、在线协作等。WebSocket通过建立初始的HTTP握手连接,然后升级到WebSocket连接。

百锦再的博客 1万+

c++ 游戏服务器框架socket

c++ 游戏服务器框架socket 包括服务器 客户端 ,项目剥离

Linux网络编程:socket、客户端服务器端使用socket通信(TCP)

Linux网络编程:socket、客户端服务器端使用socket通信(TCP)

坚持学习 4757

基于STM32智能震动报警器震动检测声光报警系统设计

*单片机设计介绍,基于STM32智能震动报警器震动检测声光报警系统设计。

2201_75940997的博客 2149

AI开发助手介绍

AI开发助手介绍随着NLP方向发展越来越成熟,AI写代码领域出现了几个非常好的模型,今天笔者给大家推荐几个AI Coding 助手AI Coding助手是以IDEA插件或vim插件形式提供服务,在编辑器中写代码时,可以实时预测下一行要输入的代码,提升开发效率。Github Copilot首先要介绍的是Github Copilot,Copilot是个AI Coding助手,它从注释和代码中提取上下文,给出单行和整个函数的代码建议,Copilot由Open AI 的CodeX模型提供支持,它是一个由OpenAI

bobo_simpler的博客 5765

WebSocket 与 Socket、TCP、HTTP:选择正确的协议方式

Websocket是一种新型的协议,它允许客户端和服务器之间建立实时的双向通信通道。 ​

2469

TypeScript领域建模实战:基于斯坦福本体论七步法构建健壮数据模型

在软件工程中,领域建模是连接业务需求与技术实现的关键桥梁,其核心在于对业务概念、属性及其关系的显式定义与规范。通过系统化的建模方法,开发者能够将模糊的领域知识转化为清晰、可扩展且类型安全的数据结构,从而在编译时捕获潜在错误,提升代码质量与可维护性。这一过程的技术价值在于实现了从业务逻辑到类型系统的无损映射,确保了设计的一致性。在实践中,结合TypeScript的静态类型检查与Zod的运行时验证,可以构建起从概念到代码再到数据库的三层一致性约束。本文以电商、博客等常见应用场景为例,深入解析如何运用源自斯坦福知

weixin_42551967的博客 383

C++游戏服务器框架笔记(二)_封装Socket类

C++封装Socket类

木可的博客 7256

TI DSP的 FFT与IFFT库函数的使用测试

/** * Copyright (C) 2013 Guangzhou Tronlong Electronic Technology Co., Ltd. - www.tronlong.com * * @file dsplib_fft.c * * @brief Example application main file. * This application will run FFT performance test. * * @author Tronlong <support@tron.

ToneChip的专栏,一个传统的嵌入式码农,裸机编程 2677

智慧安防:基于Java+YOLOv8的视频AI识别平台设计与实现

张工,我们的园区智慧安防项目又出问题了!用Python写的YOLOv8 demo,拉3路RTSP流就卡,视频延迟超过5秒,入侵检测误报率太高,一到晚上光线差就全是误报,而且和我们的Java安防平台对接太麻烦,还要搭个消息队列,架构复杂得要死!“别慌,用Java+YOLOv8啊!

2601_94871597的博客 196

游戏服务端架构学习笔记

一 概述游戏服务器的本质就是基于长连接的socket服务器。 它利用socket通讯来实现服务器与客户端之间的交互。事实上有不少游戏是直接基于原生socket来开发的。 相对于简单的socket服务器,它承受着更加繁重的任务: 后端承载着极复杂的游戏逻辑。 网络流量与消息量巨大,且实时性要求高。 通常一台socket服务器无法支撑复杂的游戏逻辑,因此往往使用一个服务器集群来提供服务。...

weixin_30782293的博客 187

Odoo17商城微信支付模块,快速一个实现可在线支付的商城

通过集成微信支付APIv3,Odoo 系统实现了高效、安全的支付流程。Native扫码支付和Jsapi微信浏览器内直接拉起支付为用户提供了更加便捷的支付方式。同时,通过发送下单及支付消息给管理员,商家可以实时了解订单状态并进行相应处理。通过集成微信支付 结合 Odoo 系统内置的商城模块,可以为商家快速实现功能完善、高效的电商解决方案。

AaronZZH 的博客 2268

游戏服务器开发指南(目录)

本目录用于游戏服务器开发指南系列,分门别类存放文章的链接地址,方便读者快速索引。目录按不同的主题组织,如网络通信、数据存储等,每个主题会包含若干篇文章。个人计划是平均每周写一篇,写作基于平时工作中产生的灵感,因此不一定会按照主题的排列顺序来。

长三月的游戏开发 400

姿态传感器/陀螺仪之LSM6DS3TR-C应用原理图设计

LSM6DS3TR-C是一款由意法半导体(STMicroelectronics)推出的高性能、低功耗的惯性测量单元(IMU),集成了3轴加速度计和3轴陀螺仪,用于测量加速度、角速度以及设备的姿态和运动。

corlin6688的博客 872

Apollo Planning决策规划算法代码详细解析 (2):Scenario执行

上一章节讲Scenario的决策逻辑,当确认当前Scenario后,本章节继续深入讲解在代码中,Scenario的执行过程。Scenario的Process()函数根据配置文件顺序执行stage,并判断目前处于哪个stage。当确认好stage后调用该stage对应的Process()函数,来进行具体的规划任务。 码字不易,喜欢的朋友们麻烦点个关注与赞。 在本文你将学到下面这些内容: Scenario的Process()函数的作用于调用方式; Scenario对象的初始化方法; 如何给每个Scen

自动驾驶Player的博客 5609

Linux 游戏服务器开发

.

Kali 忠实粉丝 767

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

如何快速掌握Skynet游戏服务器框架:从零开始的终极指南

你是否正在寻找一款轻量级且高效的游戏服务器框架?想要构建高性能的在线游戏服务却不知从何入手?本文将为你提供完整的Skynet框架入门教程,通过3个核心步骤带你快速掌握这个在中国游戏行业广泛应用的轻量级游戏服务器框架。 Skynet是一个基于Actor模型的多用户Lua框架,专为在线游戏开发设计。作为一款轻量级游戏服务器框架,它具有内存占用低、并发性能强、模块化设计等优势。本文将为你揭示Skyne

gitblog_00981的博客 670

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

当前常见游戏服务器引擎

当前常见游戏服务器引擎 时间:2020-12-08 这里搜罗总结了一些资料,可以作为参考。 要注意,不论使用哪种游戏服务器引擎,都需要了解学习游戏服务器相关概念和知识,大多数游戏服务器引擎仅仅解决最底层的问题,部分引擎还需要二次开发,而游戏的实际服务逻辑往往需要自己从零写起,并且游戏越复杂,需要考虑的问题就越多。 很多游戏项目组,并不使用商业化/开源引擎,而是自己开发一套自研引擎,不在讨论范围内。 本人只用过skynet和pomelo,对其他引擎的描述可能不准确。 一、商业化引擎 bigworld 一款来自

Nicker_的专栏 6798

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

C++ 游戏服务器开发从 Socket 到广播,手写多人在线服务器

本文以一个多人在线对战游戏服务器为例,从零开始演示 C++ 网络编程的核心技术:Socket 创建与监听、多线程客户端处理、自定义文本协议设计,以及实时位置广播。文章配有完整可运行的代码,适合有 C++ 基础、想入门服务器开发的读者。

hello.reader 714

hpsocketdemo使用说明:基于 HP-SOCKET 的服务器客户端通信演示

hpsocketdemo使用说明:基于 HP-SOCKET 的服务器客户端通信演示 【下载地址】hpsocketdemo使用说明 hpsocket demo 是一个基于 HP-SOCKET 引擎的服务器客户端示例程序,展示了高效的网络通信实现。服务器端支持用户密码表认证、连接状态统计和请求队列管理,确保数据安全与传输效率...

gitblog_06768的博客 723

Requests-HTML 实战指南:用 Python 优雅地解析 HTML、渲染 JavaScript 与异步抓取

Requests-HTML 是一个把「网页抓取与 HTML 解析」变得像 Requests 请求一样直观的 Python 库:它内置了 CSS 选择器(PyQuery)、XPath、模拟浏览器 User-Agent、自动跟随重定向、连接池与 Cookie 持久化,并通过 pyppeteer 驱动 Chromium 实现完整的 JavaScript 渲染能力,还附带同步与异步两套会话接口。本文基于本

gitblog_00278的博客 982

如何快速搭建传奇游戏服务器:开源C框架完整指南

OpenMir2是一款基于C#开发的开源传奇游戏服务器框架,支持在线多人互动和经典1.76版本客户端。作为一款成熟的开源游戏服务器解决方案,它提供了完整的微服务架构,让开发者能够快速搭建属于自己的传奇世界。 ## 项目亮点解析 OpenMir2的核心优势在于其现代化的技术架构和模块化设计。项目采用.NET Core技术栈,实现了高度解耦的服务组件,每个模块都可以独立部署和维护。这种设计不仅提升

gitblog_00270的博客 174

服务器开发—谈谈游戏服务器有哪些服务

昨天,我“收到”了一个定时炸弹,当然也是爆炸了我才知道,原来我也有定时炸弹,说起来很杯具,是这我下半年“收到”的第二个定时炸弹;好了,下面我就介绍下我这定时炸弹,希望大家能减少定时炸弹         第一定时炸弹:炸弹的具体时间忘记了,大概是7月26号左右,记得爆炸的前一天晚上8点多,游戏实时在线人数一下子跌了200人,然后又好了;这时我也收到了电话,第一时间就怀疑是不是重启了,查了,

专注于C/C++数据结构、算法的研究与探讨 2989

Moon与NoahGameFrame对比分析:选择最适合你的游戏服务器框架终极指南

在游戏服务器开发领域,选择合适的框架至关重要。今天我们将深入对比两个优秀的游戏服务器框架:**Moon**和**NoahGameFrame**,帮助你做出明智的选择。这两个框架都采用了Actor模型,但在设计理念、实现方式和适用场景上有着显著差异。 ## 🎯 框架定位与设计哲学 ### Moon:轻量级游戏服务器框架 Moon是一个基于Actor模型的轻量级游戏服务器框架,采用C++17和L

gitblog_00051的博客 361

如何快速掌握HP-Socket:高性能网络通信组件的终极指南

HP-Socket是一个功能强大、性能卓越的TCP/UDP/HTTP通信组件,专为大规模高并发场景设计。作为开源的高性能网络框架,HP-Socket采用IOCP/EPOLL通信模型,结合内存池和私有堆技术,实现了高效的内存管理。无论你是网络编程新手还是经验丰富的开发者,本文将为你提供完整的HP-Socket学习路径和实战技巧,帮助你在短时间内掌握这个强大的网络通信框架! ## 核心挑战分析:现代

gitblog_00809的博客 643
上一篇: 游戏服务器开发指南(序)
下一篇: 游戏服务器开发指南(目录)
长三月
博客等级 码龄9年 228粉丝 80原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值