本篇核心知识点:Socket 定义、IP 与端口作用、长连接 / 短连接区分、进程 / 线程 / 协程区别、高并发场景、TCP 三次握手 / 四次挥手、服务器日志 Log4Net、Socket Select 多路复用、客户端连接管理、心跳包机制、时间戳计算、服务端完整运行架构、try-catch 异常捕获
一、Socket 基础概念
1 概念
Socket 是一套通信端点接口,用于两个程序(客户端 / 服务)建立数据传输通道,由 IP 地址 + 端口唯一标识一条通信链路,是网络游戏客户端与服务通信底层核心。
2 特性 / 规则
-
IP 作用:定位网络中一台物理设备(电脑 / 手机服务器);
-
端口作用:区分同一设备上多个不同程序服务,一台机器多个程序占用不同端口;
-
知名固定端口:80 网页、8080 后台服务、22 远程、3389 远程桌面;
-
游戏项目 95% 采用 Socket 长连接架构,网页 HTTP 属于短连接。
3 语法 & 代码片段
// 引入网络命名空间
using System.Net.Sockets;
using System.Net;
// 创建服务端监听Socket
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 绑定本机IP与端口
// private string ipStr = "127.0.0.1"; // 自定义ip
// private int port = 8011; // 自定义端口
// IPAddress ip = IPAddress.Parse(ipStr); // ip字符串转ip地址
// IPEndPoint endPoint = new IPEndPoint(ip, port);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 8899);
listenSocket.Bind(endPoint);
// 开启监听 数量上限1000
listen.Listen(1000);
4 相关知识点对比
长连接 Socket VS HTTP 短连接
Socket 长连接:连接建立后持续保持,服务端可主动推送消息,网游必备;
HTTP 短连接:每次刷新 / 请求新建链路,服务端无法主动发消息,网页、后台管理系统使用。
5 模块拓展
网游场景区分:MMORPG 多人主城高并发强需求 Socket;回合 / 射击房间类数据量小,网络压力更低。
二、进程、线程、协程三者区分
1 概念
-
进程:操作系统资源分配最小单元,独立软件程序(微信、VS、游戏客户端),拥有独立内存;
-
线程:CPU 调度最小执行单元,属于进程内部执行分支,同一进程多线程可并发执行;
-
协程:线程内分段执行逻辑,非独立线程,Unity 主线专用,服务端较少使用。
2 特性 / 规则
-
资源仅分配给进程,线程共享所属进程全部内存资源;
-
同进程线程可直接交互,跨进程通信成本极高;
-
并发支持:线程可实现高并发处理大量客户端连接;
-
调度层级:进程 = 资源载体,线程 = 执行调度载体。
3 语法 & 代码片段
服务端多线程简易示意片段
// 新开子线程处理Socket循环
Thread serverThread = new Thread(ServerMainLoop);
serverThread.IsBackground = true;
serverThread.Start();
4 相关知识点对比
进程 VS 线程
进程:独立内存、独立资源,跨进程通信开销巨大;
线程:共享进程内存,并发效率高,服务端处理连接标准方案。
5 模块拓展
高并发参考:12306 铁路系统海量请求,依靠多线程 + 分布式架构承载流量。
三、网络基础:延迟与带宽
1 概念
-
延迟:客户端发送消息→服务接收→返回完整耗时;
-
带宽:单位时间可传输数据总量,海量玩家同屏会占用大量带宽资源。
2 特性 / 规则
-
传奇类多人同屏主城延迟、带宽压力极高;
-
王者 / LOL 房间制仅 10 人交互,网络压力小;
-
隧道、切后台会造成临时网络断开,区分内存崩溃与心跳超时掉线。
3 相关知识点对比
高延迟场景 VS 低延迟场景
多人 MMO 主城:大量玩家同步位置、技能,延迟敏感;
房间竞技:单局人数固定,同步数据少,延迟容忍度更高。
4 模块拓展
服务器分区逻辑:单服承载千人以内,拆分多区分割并发压力。
四、Log4Net 服务端日志组件
1 概念
第三方日志记录库,服务端运行所有报错、连接、操作记录持久写入本地文本,线上出现 bug 可回溯日志定位问题。
2 特性 / 规则
-
VS 工具->NuGet 包管理器->管理解决方案 浏览在线安装,优先选择稳定旧版本,新版存在未知 Bug;
-
配置文件设置日志输出格式、存储目录;
-
程序运行自动生成日志文件夹,日志精确到时分秒;
-
项目输出目录设置:配置文件复制到输出目录(如果较新则复制)。
3 语法 & 代码片段
// 日志打印
log.Info("服务器启动监听成功");
log.Error("客户端连接异常:" + ex.Message);
4 相关知识点对比
原生 Console 打印 VS Log4Net 持久日志
Console:仅控制台临时输出,程序关闭全部丢失;
Log4Net:持久本地文件,线上运维排查 bug 必备。
5 模块拓展
日志分级:Info 正常流程、Error 异常崩溃、Warn 警告操作。
五、Socket 多路复用 Select 机制
1 概念
Select 函数一次性监听全部 Socket 集合,自动筛选存在可读数据的套接字,避免无意义循环空跑,大幅降低 CPU 占用,服务端标准高效 IO 处理方案。
2 特性 / 规则
-
传入三类集合:可读列表、可写列表、异常列表,仅处理可读连接;
-
超时单位微秒,设置极小值保证循环响应速度;
-
筛选后仅分两类处理:新客户端连接请求 、已有客户端收发数据。
3 语法 & 代码片段
List<Socket> readList = new List<Socket>();
// 填充全部监听+客户端Socket
readList.Add(listenSocket);
foreach(var client in clientDict.Values)
read.Add(client.clientSocket);
// 多路复用筛选可读Socket
Socket.Select(readList, null, null, 1000);
4 相关知识点对比
死循环轮询所有 Socket VS Select 多路复用
无脑循环:CPU 持续高占用,大量空循环无效判断;
Select:仅处理有数据连接,空闲时挂起等待,性能大幅优化。
5 模块拓展
万级连接服务端全部采用 IO 多路复用架构。
六、客户端连接管理架构
1 概念
使用 Dictionary 字典存储全部客户端连接信息,Key=Socket、Value = 自定义客户端类,统一管理连接、断开、心跳检测。
2 特性 / 规则
-
自定义 Client 类:存储客户端 Socket、最后通信时间戳;
-
字典全局缓存所有在线玩家,快速遍历查找;
-
逆序遍历 Socket 列表,优先处理已有客户端数据,最后处理新连接请求。
3 语法 & 代码片段
// 存储全部在线客户端
Dictionary<Socket, ClientInfo> clientDict = new Dictionary<Socket, ClientInfo>();
// 客户端信息实体
public class ClientInfo{
public Socket clientSocket;
public long lastRecvTime; // 最后收发时间戳
}
4 相关知识点对比
List 存储连接 VS Dictionary 存储连接
List:查找指定客户端需要循环遍历,效率低;
Dictionary:通过 Socket 键直接取值,查找 O (1) 效率。
5 模块拓展
玩家下线、踢人、批量离线操作基于字典遍历实现。
七、时间戳计算(UTC 标准)
1 概念
以 1970-01-01 00:00 UTC 为起点计算总毫秒数,不受电脑本地修改时间影响,服务端统一计时、活动倒计时、心跳判断标准方案。
2 特性 / 规则
-
本地 DateTime.Now 可人为修改,时间戳不受系统时间改动干扰;
-
长整型存储毫秒时间戳,用于心跳超时、活动倒计时差值计算。
3 语法 & 代码片段
// 获取UTC标准时间戳
TimeSpan timeSpan = DateTime.UtcNow - new DateTime(1970,1,1,0,0,0,0);
long time = Convert.ToInt64(timeSpan.TotalSeconds);
4 相关知识点对比
本地 DateTime VS UTC 时间戳
DateTime.Now:用户可手动修改电脑时间,逻辑会错乱;
UTC 时间戳:全球统一标准,服务端计时、校验唯一标准。
5 模块拓展
活动倒计时、离线时长、登录间隔全部使用时间戳差值运算。
八、try-catch 异常捕获
1 概念
捕获代码运行异常,防止单个客户端报错导致整个服务器进程闪退,保证服务 7*24 小时稳定运行。
2 特性 / 规则
-
所有 Socket 读写、连接逻辑包裹 try-catch;
-
捕获异常后打印 Error 日志,继续循环接收新连接;
-
客户端异常断开、数据解析报错不会影响整体服务。
3 语法 & 代码片段
try{
Socket newClient = listenSocket.Accept();
}
catch(Exception ex){
log.Error("接收客户端连接异常:" + ex.ToString());
}
4 相关知识点对比
无捕获直接运行 VS try-catch 捕获
无捕获:任意客户端异常直接导致服务程序崩溃;
捕获:单连接错误隔离,服务持续运行。
5 模块拓展
数据解析、数据库操作、文件读写全部加异常捕获。
九、心跳包超时检测机制
1 概念
客户端定时向服务发送空心跳数据包,服务记录最后接收时间;超过指定时长未收到心跳则判定掉线,主动关闭 Socket 释放资源。
2 特性 / 规则
-
基础心跳间隔 30 秒,预留容错倍数(2~3 倍)防止临时断网误踢;
-
手机切后台、隧道弱网不会直接踢下线,预留缓冲窗口;
-
遍历全部客户端字典,对比当前时间戳与最后通信时间戳。
3 语法 & 代码片段
long nowTs = GetUtcTimeStamp();
List<ClientSocket>m_TempList = new List<ClientSocket>();
long heartLimit = 30; // 容错30s
foreach(ClientSocket clientSocket in clientDict.Value){
if(nowTs - clientSocket.lastRecvTime > heartLimit * 4){
m_TempList.Add(clientSocket); // 超时断开
}
}
// 对心跳包超时的客户端进行统一处理
foreach(ClientSocket client in m_TempList){
CloseClient(client);
}
m_TempList.Clear();
4 相关知识点对比
心跳踢下线 VS 程序内存崩溃掉线
心跳:网络弱、切后台、断网超时正常处理;
内存崩溃:系统直接销毁进程,无断开逻辑。
5 模块拓展
游戏切后台、锁屏、飞行模式全部依靠心跳机制处理离线逻辑。
十、服务端完整生命周期架构
1 概念
服务标准执行循环:启动监听 Socket→多路复用筛选可读连接→分新连接 / 已有客户端处理→心跳超时清理→循环往复。
2 特性 / 规则
-
启动阶段:绑定端口、开启监听、初始化日志、创建客户端字典;
-
循环阶段:Select 筛选 Socket、优先处理玩家数据、再处理新连接;
-
收尾阶段:心跳遍历清理超时离线客户端;
-
全程子线程运行,主线程控制台可打印状态。
3 语法 & 代码片段
void ServerMainLoop(){
InitServer(); // 初始化监听、日志
while(true){
List<Socket> readList = GetAllSocket();
Socket.Select(readList,null,null,1000);
DealAllReadSocket(readList); // 处理连接与数据
CheckHeartTimeout(); // 心跳清理
}
}
4 相关知识点对比
线性单次执行 VS 死循环服务架构
单次执行:处理一次直接退出,无法持续接收玩家;
永久循环:持续监听在线玩家,游戏服务标准架构。
5 模块拓展
拓展功能:消息序列化、数据库读写、玩家数据存档、协议分发。
综合拓展
1 服务端开发规范:全部 IO 操作加 try-catch、统一 UTC 时间戳计时、多路复用替代无脑循环、日志分层记录,禁止 Console 临时输出。
2 高频 Bug 排查清单
连接大量占用 CPU:未使用 Select 多路复用;
玩家无故掉线:心跳超时时间设置过短无容错;
日志无输出:Log4Net 配置文件未复制到输出目录;
服务无法接收连接:端口被占用、IP 绑定错误。
3 面试核心考点
Socket 长连接 / 短连接区别、Select 多路复用原理、心跳包作用、UTC 时间戳优势、进程线程协程区分、Log4Net 日志使用、服务主循环架构。
4 进阶拓展学习方向
Protobuf 二进制协议、MySQL 数据库玩家存档、分布式多服架构、断线重连、消息分发器、异步 IO 模型。