游戏局域网联机方案:服务端搭建、UDP广播发现与防火墙配置 📅 发布时间:2026/9/3 10:24:11 👁 浏览次数: 做游戏联机最容易踩的坑是什么很多人一想到“游戏要支持多人同时在线”第一反应就是买云服务器、申请公网 IP、部署一套 WebSocket 服务端再配 MySQL 和 Redis最后还要处理 NAT 穿透、负载均衡、网络抖动。这套链路不是不对而是绝大多数项目在玩法验证阶段根本走不到这一步服务器账单却已经先来了。《BigWalk》是一个以步行探索、社交互动为核心玩法的轻量级元宇宙项目。项目现阶段最需要的不是支撑十万人在线的云架构而是先让三五个测试玩家在同一局域网里稳定地走动、对话、触发事件。说直白一点先把局域网联机跑通再谈公网和并发。这篇文章会以《BigWalk》为例给出一个可以落在本地的局域网联机完整方案覆盖服务端监听、广播发现、客户端连接、防火墙放行、联机验证和常见排错。读完以后你应该能在一台电脑上启动服务端让同一局域网内另外几台电脑上的客户端稳定加入游戏并且知道每一步为什么这样做、失败时先看哪里。1. 为什么局域网联机是《BigWalk》阶段性的正确选择1.1 联机机制不是附加功能而是元宇宙的核心玩法如果一款游戏叫“元宇宙”但玩家在游戏里看不到任何人那它和单机步行模拟器没有本质区别。联机机制在这个项目里不是做完了核心玩法之后再加的补丁而是从一开始就要验证的核心体验。《BigWalk》的基础联机需求可以拆成三块位置同步玩家 A 移动时玩家 B 的客户端要实时看到 A 的位置变化。状态共享场景里的门、箱子、NPC 交互结果所有客户端要保持一致。事件分发A 触发了某个任务或特效B 也要收到同样的广播。这三块在局域网里实现网络延迟通常在 1ms 到 5ms 之间远低于公网常见的 30ms 到 100ms。对玩法验证来说这是一个干扰最少的环境。1.2 局域网联机的三个直接收益第一成本接近于零。不需要租服务器不需要带宽费用一台宿舍里的 Windows 电脑就可以当作服务端。第二调试效率高。客户端和服务端都在同一个物理网络里日志可以并排看断点可以同时打。服务端崩了直接重启没有远程运维的负担。第三逼迫你把“服务端边界”想清楚。很多人做联机游戏喜欢把逻辑堆在客户端。但在局域网联机版本里你必须要回答一个问题哪些数据由服务端决定哪些数据由客户端上报。这个边界一旦定清楚后面迁移公网会非常顺。1.3 什么时候不该用局域网联机局域网不是万能的。如果《BigWalk》的测试玩家分布在不同的城市那局域网方案完全不适用。另外如果项目要验证的是“极端弱网下的表现”或“千人同屏的压力测试”局域网环境也提供不了这种场景。更稳妥的判断是局域网联机是开发期和封闭测试期的手段不是产品最终形态。它解决的问题是“把联机玩法先跑起来”而不是“把架构一步做到生产级”。2. 联机架构P2P、独立服务端与局域网广播设计2.1 P2P 房间制P2P 模式里一个玩家创建房间其他玩家直接连接房主。房主的电脑既跑游戏又承担同步逻辑。优点是省一台服务器适合两个人临时联机。缺点是房主的网络和机器性能会直接影响所有玩家而且如果房主掉线整局就崩了。对《BigWalk》来说P2P 适合快速原型验证但不适合作为长期方案。因为元宇宙项目后续要加入任务系统、世界状态持久化这些逻辑放在房间内运行的玩家设备上并不合理。2.2 客户端-服务器模式独立服务端模式中有一个专门的进程负责维护世界状态、接收玩家输入、广播游戏事件。客户端只负责表现层和输入采集。这是目前网络游戏的主流架构也更容易迁移到公网。服务端写好了后续无非是把进程部署到云主机再把网络层从局域网换成公网协议核心逻辑不需要推翻重来。《BigWalk》局域网联机版本采用的就是这个方案下文所有配置和代码都基于它展开。2.3 局域网广播发现服务端启动后客户端怎么知道服务端的 IP 和端口最原始的方法是手动输入 IP。但局域网里 DHCP 会动态分配地址今天服务端是 192.168.1.100明天可能就变成了 192.168.1.105。每次联机都要先跑到服务端那台机器上看 IP体验很差。所以更合理的方案是让服务端启动时周期性地向局域网广播一条 UDP 消息消息里包含游戏名、服务端名称、端口、当前玩家数等信息。客户端在局域网内监听广播消息收到后自动把服务器列出来。广播发现减少的是配置成本它让“打开客户端就能看到局域网房间”成为可能。不过需要注意UDP 广播默认只在同一网段内传播如果两台电脑不在同一个 VLAN 或没有使用组网工具广播是收不到的。2.4 两种模式的核心对比对比维度P2P 房间制客户端-服务器模式额外设备不需要需要一台常开电脑逻辑权威房主服务端房主掉线影响全房间崩溃客户端掉线不影响其他人后续迁移公网改造困难服务端可直接部署适合阶段快速原型正式联机验证3. 环境准备硬件、网络与项目目录规划3.1 网络环境最基础的局域网联机环境只需要一台路由器加两台电脑两台电脑连接到同一个路由器处于同一个网段。需要确认以下几点两台电脑都能正常上网并且能互相 ping 通。路由器 DHCP 开启默认是开启的。如果公司或学校网络开启了 AP 隔离需要找管理员调整否则设备之间无法互相访问。无线网络可以用但联机测试优先使用有线网络可以排除无线丢包带来的干扰。3.2 操作系统与运行时本文示例在 Windows 10 / Windows 11 上运行。服务端示例使用 .NET 编写因此需要安装 .NET SDK 或者 .NET Runtime版本以你实际安装为准文章重点演示通用思路。之所以用 .NET 举例是因为 Unity 客户端也是 C# 技术栈服务端和客户端可以共享一部分数据结构和消息定义。即使你的《BigWalk》客户端使用别的引擎只要理解了网络通信原理换成 Go、Java、Node.js 服务端都只是语法替换的问题。3.3 项目目录规划BigWalk/ ├── Client/ # Unity 客户端 │ ├── Assets/ │ │ ├── Scripts/Network/ # 网络连接、广播发现脚本 │ │ └── Scenes/ # 游戏场景 │ └── ProjectSettings/ ├── Server/ # 独立服务端 │ ├── Config/ │ │ └── server_config.yaml │ ├── BigWalk.Server/ # 服务端源码 │ └── scripts/ # 启动脚本 ├── Tools/ # 联机测试工具 └── Docs/ # 联机部署文档把客户端和服务端拆开有两个好处一是服务端不依赖 Unity 编辑器启动更快二是后续上公网时服务端可以直接部署到 Linux 云主机不需要跟随项目完整安装客户端。4. 服务端搭建配置文件、TCP 监听与 UDP 广播4.1 服务端配置文件服务端需要一个配置文件把端口、玩家上限、广播开关等参数外置避免每次修改都要重新编译。这里以server_config.yaml为例# Server/Config/server_config.yaml server: name: BigWalk-LAN-Server bind_ip: 0.0.0.0 port: 7777 max_players: 16 tick_rate: 30 broadcast: enabled: true port: 47777 interval_seconds: 2 world: name: default_world save_path: /data/bigwalk/worlds/default字段含义bind_ip服务端监听地址。填0.0.0.0表示监听本机所有网卡局域网内其他设备才能连进来。port游戏 TCP 连接端口客户端需要连到这个端口。tick_rate服务端每秒处理逻辑的次数类似“每秒刷新多少帧游戏状态”。broadcast.portUDP 广播端口客户端监听这个端口来发现服务器。4.2 服务端主程序下面是一个最小可运行的服务端示例只做两件事启动 TCP 监听接收玩家连接启动 UDP 广播让客户端能发现它。// Server/BigWalk.Server/Program.cs using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; namespace BigWalk.Server { public static class Program { private static int _tcpPort 7777; private static int _broadcastPort 47777; public static async Task Main(string[] args) { // 简单解析命令行参数实际项目通常从配置文件读取 ParseArgs(args); Console.WriteLine($[BigWalk] Server starting... TCP port: {_tcpPort}); var tcpListener new TcpListener(IPAddress.Any, _tcpPort); tcpListener.Start(); Console.WriteLine($[BigWalk] TCP listener started on port {_tcpPort}); // 启动 UDP 广播线程 var broadcastCts new CancellationTokenSource(); _ Task.Run(() BroadcastLoop(broadcastCts.Token)); // 接收玩家连接的循环 while (true) { var client await tcpListener.AcceptTcpClientAsync(); _ HandleClient(client); } } private static async Task HandleClient(TcpClient client) { var remote client.Client.RemoteEndPoint?.ToString(); Console.WriteLine($[BigWalk] Player connected: {remote}); try { using var stream client.GetStream(); var buffer new byte[2048]; int readCount await stream.ReadAsync(buffer, 0, buffer.Length); if (readCount 0) { var message Encoding.UTF8.GetString(buffer, 0, readCount); Console.WriteLine($[BigWalk] Received first message: {message}); } } catch (Exception ex) { Console.WriteLine($[BigWalk] Client error: {ex.Message}); } finally { client.Close(); } } private static async Task BroadcastLoop(CancellationToken token) { using var udp new UdpClient(); udp.EnableBroadcast true; var broadcastAddr new IPEndPoint(IPAddress.Broadcast, _broadcastPort); while (!token.IsCancellationRequested) { var json {\game\:\BigWalk\,\server\:\BigWalk-LAN-Server\,\port\:7777,\players\:0,\max_players\:16}; var bytes Encoding.UTF8.GetBytes(json); await udp.SendAsync(bytes, bytes.Length, broadcastAddr); Console.WriteLine($[BigWalk] Broadcast sent to {broadcastAddr}); await Task.Delay(TimeSpan.FromSeconds(2), token); } } private static void ParseArgs(string[] args) { for (int i 0; i args.Length; i) { if (args[i] --port i 1 args.Length) { _tcpPort int.Parse(args[i 1]); } else if (args[i] --broadcast-port i 1 args.Length) { _broadcastPort int.Parse(args[i 1]); } } } } }这个示例看起来简单但已经覆盖了局域网联机服务端的两个核心能力连接接入和信息广播。真正进入游戏逻辑后你会在HandleClient里扩展位置同步、状态处理、消息编解码但网络骨架不会变。4.3 编译与启动服务端在项目根目录执行cd Server/BigWalk.Server dotnet run启动成功后日志里会出现TCP listener started on port 7777随后每两秒输出一条Broadcast sent。如果能看到这两句服务端的网络基础层已经通了。5. 客户端接入固定 IP 直连、广播发现与连接状态管理5.1 固定 IP 直连最直接的接入方式是在客户端输入服务端电脑的局域网 IP 和端口。先在服务端电脑上执行ipconfig获取 IPipconfig重点看“无线局域网适配器”或“以太网适配器”下的 IPv4 地址通常是192.168.x.x。把这个 IP 填到客户端的连接面板里端口填7777。好处是省事适合两个人临时联机。缺点前面说过IP 可能变化不适合常态化使用。5.2 客户端连接代码以下是 Unity 客户端中一个最小连接示例使用 C# 的TcpClient连接服务端并发送一条 JSON 消息// Client/Assets/Scripts/Network/BigWalkClient.cs using System; using System.Net.Sockets; using System.Text; using UnityEngine; public class BigWalkClient : MonoBehaviour { private TcpClient _client; private NetworkStream _stream; public void ConnectToServer(string ip, int port) { try { _client new TcpClient(); _client.Connect(ip, port); _stream _client.GetStream(); var joinMessage {\type\:\join\,\playerName\:\Player1\,\x\:0,\y\:0}; var bytes Encoding.UTF8.GetBytes(joinMessage); _stream.Write(bytes, 0, bytes.Length); Debug.Log($[BigWalkClient] Connected to {ip}:{port}); } catch (SocketException ex) { Debug.LogError($[BigWalkClient] Connection failed: {ex.Message}); } } void OnDestroy() { _client?.Close(); } }这里真正容易踩坑的地方是服务端监听的是0.0.0.0客户端连接时不能填0.0.0.0必须填服务端电脑的实际局域网 IP。很多第一次联机的人在这里卡住以为服务端绑定了所有网卡客户端就能用任意地址连实际上客户端的目标地址必须是可达的具体 IP。5.3 UDP 广播发现为了让客户端自动发现局域网内的《BigWalk》服务器客户端可以启动一个 UDP 监听器接收服务端发来的广播消息。// Client/Assets/Scripts/Network/BigWalkDiscovery.cs using System; using System.Net; using System.Net.Sockets; using System.Text; using UnityEngine; public class BigWalkDiscovery : MonoBehaviour { private UdpClient _udpClient; private bool _running; void Start() { _udpClient new UdpClient(47777); _udpClient.EnableBroadcast true; _running true; _udpClient.BeginReceive(new AsyncCallback(OnReceive), null); } private void OnReceive(IAsyncResult ar) { if (!_running) return; try { var remote new IPEndPoint(IPAddress.Any, 0); var bytes _udpClient.EndReceive(ar, ref remote); var message Encoding.UTF8.GetString(bytes); Debug.Log($[BigWalkDiscovery] Found server from {remote.Address}: {message}); // 这里可以把服务器信息加入 UI 列表 _udpClient.BeginReceive(new AsyncCallback(OnReceive), null); } catch (Exception ex) { Debug.LogError($[BigWalkDiscovery] Receive error: {ex.Message}); } } void OnDestroy() { _running false; _udpClient?.Close(); } }需要提醒的是在 Unity 编辑器中测试 UDP 监听时Windows 防火墙通常会弹出首次访问提示必须勾选“专用网络”并允许访问否则广播消息会被系统防火墙静默丢弃。6. 防火墙放行与局域网连通性调试6.1 放行 TCP 游戏端口和 UDP 广播端口即使代码没有写错Windows 防火墙也经常成为联机失败的“隐形杀手”。最稳妥的方式是手动添加入站规则提前放行服务端需要监听的端口。在管理员 PowerShell 中执行New-NetFirewallRule -DisplayName BigWalk TCP 7777 -Direction Inbound -Protocol TCP -LocalPort 7777 -Action Allow New-NetFirewallRule -DisplayName BigWalk UDP 47777 -Direction Inbound -Protocol UDP -LocalPort 47777 -Action Allow注意这两条规则只需要在服务端电脑上执行。客户端通常不需要额外放行但如果客户端要监听 UDP 端口做广播发现也需要在客户端机器上放行 UDP 47777 入站。6.2 网络连通性检查如果客户端还是连不上按顺序做以下检查第一步确认两台电脑能互相 ping 通ping 192.168.1.100如果 ping 不通先检查是否在同一网段、路由器是否开启了 AP 隔离。第二步确认服务端端口正在监听netstat -ano | findstr 7777如果没有输出说明服务端没有启动成功或者监听端口被其他程序占用。第三步从客户端机器测试 TCP 端口连通性Test-NetConnection 192.168.1.100 -Port 7777输出中TcpTestSucceeded : True才是正常状态。如果这里显示 False基本可以确定是防火墙拦截或服务端没启动。6.3 虚拟局域网组网工具如果测试玩家不在同一个物理网络但又想使用局域网联机方案可以使用虚拟局域网组网工具比如 Radmin LAN。这类工具会把分布在不同地点的多台设备通过加密隧道组合成一个虚拟局域网设备之间获得类似局域网的访问体验。这类工具适合小范围朋友联机测试也适合《BigWalk》在多地区小规模内测时使用。但需要记住虚拟局域网依然依赖公网链路实际延迟会明显高于物理局域网不要把它当成延迟优化手段。7. 联机验证与性能观察7.1 启动顺序正确的启动顺序是先启动服务端再启动客户端。如果你先开了客户端客户端广播发现阶段会一直收不到服务器信息直到服务端上线后下一个广播周期到来才会发现。推荐流程在服务端电脑启动dotnet run。看到TCP listener started on port 7777后启动 Unity 客户端。客户端启动后进入联机界面等待自动发现服务器或手动输入服务端 IP。点击连接后观察服务端控制台是否打印Player connected。7.2 预期日志服务端正常时日志大致如下[BigWalk] Server starting... TCP port: 7777 [BigWalk] TCP listener started on port 7777 [BigWalk] Broadcast sent to 255.255.255.255:47777 [BigWalk] Broadcast sent to 255.255.255.255:47777 [BigWalk] Player connected: 192.168.1.102:54321 [BigWalk] Received first message: {type:join,playerName:Player1,x:0,y:0}看到Player connected说明 TCP 连接已经建立看到Received first message说明客户端和服务端的消息格式匹配上了。7.3 需要观察的指标联机运行中重点看三个指标连接稳定性连接是否频繁掉线。频繁断开先看有没有路由器 NAT 表溢出再看服务端日志有没有异常。消息延迟从玩家 A 发送位置消息到玩家 B 看到位置变化的时间差。局域网环境应该在几十毫秒以内。丢包率执行ping 192.168.1.100 -t观察。丢包率超过 1% 时优先检查无线网络信号强度和信道干扰。7.4 单机多开测试如果暂时没有多台电脑也可以在一台电脑上启动一个服务端进程和两个客户端窗口进行联机测试。Unity 编辑器可以开多个实例但要确保每个实例使用不同的玩家数据目录否则会出现配置冲突。8. 常见问题与排查方法问题现象可能原因排查方式解决方案客户端连不上服务端服务端未启动或端口被占用netstat -ano | findstr 7777启动服务端或修改配置端口能 ping 通但连接失败防火墙拦截入站 TCPTest-NetConnection IP -Port 7777添加入站防火墙规则客户端看不到局域网服务器UDP 广播未到达客户端检查广播端口是否一致放行 UDP 47777或改用手动 IP 连接广播发现列表为空两台设备不在同一网段ipconfig对比网段调整网络或使用组网工具连接后立刻断开服务端收到非法消息并异常关闭查看服务端异常堆栈统一消息格式增加异常捕获游戏内延迟突然升高无线网络干扰或后台占用ping持续观察丢失换有线网络关闭后台下载重启后 IP 变了DHCP 动态分配ipconfig查看当前 IP在路由器中配置 DHCP 静态绑定第一次运行被防火墙拦截系统安全策略弹出拦截检查防火墙入站规则提前在管理员 PowerShell 中配置这里最容易忽视的是 UDP 广播问题。TCP 连接是显式的连不上时所有人都能意识到网络层有故障。但 UDP 广播是“发了就忘”的模型服务端以为自己在广播客户端可能根本没收到而且两边都不会有报错。遇到“广播发现列表为空”时最快的解决办法是先用固定 IP 直连验证 TCP 链路再回头排查 UDP 广播避免同时面对两个不确定项。9. 安全边界、工程化建议与下一步实践9.1 局域网也不是绝对安全很多开发者觉得“局域网”等于“安全”这个认知需要被修正。只要一台设备接入同一个局域网它就有能力进行端口扫描和流量监听。虽然《BigWalk》现阶段只是玩法验证但网络层的基本安全意识必须建立。在实际项目中至少要做到三点第一不要把服务端绑定到0.0.0.0再暴露到不可信网络。联机测试结束后关闭服务端进程不要让它长期挂在后台。第二为每个进入游戏的玩家增加简单的身份标识比如客户端生成的 token。当前示例里只发了一个玩家名这只能用来做演示生产环境需要服务端校验身份。第三后续如果加入玩家消息广播消息内容要做最大长度限制防止恶意客户端向服务端发送超大消息拖垮进程。9.2 工程化建议配置外置端口、玩家上限、广播间隔都从配置文件读取不要硬编码在代码里。日志分级服务端日志至少区分 Debug、Info、Error 三级联机问题定位时Error 日志要能直接指出哪个玩家、哪个会话、哪个方法出了异常。消息格式统一尽早把 JSON 消息体抽象成消息类不要用散落的字符串拼接。自动化测试可以写一个没有界面的一体化测试客户端模拟 10 个玩家同时连接验证服务端在预期负载下是否稳定。版本管理客户端和服务端的协议版本号要单独管理避免新旧客户端混用导致解析错误。9.3 从局域网迈向公网当《BigWalk》的玩法验证完成需要支持异地玩家联机时迁移路径其实是现成的。客户端-服务器架构下服务端可以直接部署到云主机只需把网络层从局域网广播改为公网地址或云服务发现。另一个低成本路线是虚拟局域网组网它不改变代码但受限于公网链路质量适合小规模封闭测试。真正面向大众时还是应该走完整的上线流程云服务器、负载均衡、数据库持久化、日志监控、灰度发布。9.4 下一步实践建议如果你正在开发类似《BigWalk》的联机游戏下一步建议按顺序做三件事一把网络连接代码和游戏逻辑分层。连接层只负责收发字节流游戏逻辑层只处理消息对象二者不要混在一起。二用广播发现加固定 IP 直连两种模式并行开发。一个是玩家体验的加分项一个是排查问题的保底手段。三尽早做断线重连。局域网联机虽然稳定但无线网卡休眠、路由器重启等现实问题依然存在。断线重连不是生产环境才需要的能力测试期就需要暴露和修复。局域网联机不是终点它是走向更复杂网络架构前最值得投入的第一个里程碑。把这一层跑稳《BigWalk》后面的公网联机之路会顺畅得多。