
秋招季又到了服务器开发工程师这个岗位的笔试向来是淘汰率最高的一关。我前后帮学弟学妹们改了上百份笔试题复盘也跟不少大厂面试官聊过出题思路发现很多人挂在笔试题上不是不会写代码而是根本不知道这张卷子到底在考什么。畅游这类游戏公司的服务器开发岗笔试风格很典型不跟你绕弯子题目看着基础但每一道都在往深了挖稍不注意就踩坑。这篇文章我就拿2024年秋招服务器开发工程师的笔试题作为引子把这类岗位笔试背后的考点逻辑、常考题型、解题思路和避坑经验一次讲透给正在准备秋招的你一份可以直接照着复习的路线。先说清楚这篇文章适合谁看目标岗位是服务器开发、后端研发、游戏服务端开发的应届生已经拿到笔试通知但不知道怎么系统复习的同学还有那些C/Linux基础还行、但一遇到大题就发懵的朋友。不管你是科班还是半路转码只要按着下面的思路把考点串起来笔试这关会稳很多。1. 先搞清楚服务器开发工程师笔试到底在考什么1.1 岗位能力画像笔试是能力雷达图的第一次扫描很多人以为服务器开发笔试就是考算法刷题上来就猛刷LeetCode结果进了考场发现题目跟想象中完全不一样。游戏公司也好互联网公司也罢服务器开发工程师这个岗位笔试的核心逻辑其实是画一张你的能力雷达图考察的是你能不能在复杂的分布式环境下写出稳定、高效、可维护的服务器代码。这个能力雷达图大概有五个维度操作系统原理、网络编程功底、编程语言深度、数据结构与算法、系统设计思维。笔试题目不管怎么变都是围绕这五个维度展开的。算法题只是其中一个维度而且通常占比不超过30%。剩下那70%的分数全压在你对底层原理的理解深度上。为什么这么设计因为服务器开发跟纯业务后端不一样。纯业务后端可能你搞清楚框架怎么用、数据库怎么连就能干活了。但服务器开发面对的是成千上万的并发连接、毫秒级的延迟要求、7x24小时不宕机的稳定性要求。这时候你对操作系统怎么调度线程、网络数据包怎么在内核里流转、内存碎片怎么产生的这些底层机制的理解深度直接决定了你写出来的代码是能抗压的工业级代码还是只能跑通demo的学生作品。1.2 高频考点权重与近年出题风向我统计了2022年到2024年几十家公司的服务器开发笔试题目发现考点分布其实相对稳定。这里分享一张可以当复习大纲的权重表考点模块出现频率常考题型典型知识点计算机网络极高选择题简答TCP状态机、TIME_WAIT、粘包拆包、epoll原理操作系统极高选择题简答进程线程协程、虚拟内存、死锁、多路复用C/语言基础极高选择代码输出智能指针、虚函数、内存对齐、move语义数据结构与算法高编程题LRU、TopK、海量数据、二叉树、DP系统设计中高简答设计题定时器设计、连接池、消息队列、并发模型这里有个很明显的风向变化早些年笔试题目会更偏向纯理论记忆比如让你背TCP三次握手的过程、写个快排之类的。近两年明显更侧重原理应用的结合会给你一个业务场景让你基于某个技术点去分析或者优化。比如在高并发下TCP连接太多导致性能下降你会怎么排查和处理这种题目纯靠背书是答不好的。还有一个小趋势是协程和io_uring这类相对较新的技术开始出现在选择题里。出题人不会要求你写过但至少要知道它们和传统线程模型、epoll模型的区别。这说明考察的不是你背了多少八股而是你平时有没有真的在关注技术演进。2. 核心基础模块逐个拆解从送分题到拉分题2.1 操作系统进程线程与内存管理是送分题也是送命题操作系统这块的题目表面上看都是经典八股但出题人特别喜欢在细节上挖坑。先说进程、线程、协程这个万年不变的话题。基础版本问区别进阶版本会问一个进程崩溃会不会影响其他进程一个线程崩溃会不会拖垮整个进程前者不会因为进程有独立地址空间后者大概率会因为同一进程内的线程共享地址空间。但如果你在选择题里看到线程崩溃一定导致进程退出这个一定就是坑因为有些语言的运行时会在线程异常时做隔离处理C里未捕获异常调用std::terminate会导致进程终止而Java里线程抛出未捕获异常默认也只是终止当前线程。内存管理是另一个高频拉分点。虚拟内存、页表、缺页中断、内存映射这些概念建议你串成一条线来理解进程看到的是虚拟地址空间CPU通过MMU查页表把虚拟地址翻译成物理地址访问的页不在内存里就触发缺页中断由内核从磁盘换入。这条链路讲清楚相关选择题基本都能对付。这里有个实践性很强的小知识点容易被忽略——内存对齐。笔试选择题里经常会给你一个结构体让你算sizeof等于多少然后给出一堆干扰选项。比如struct Test { char a; // 1字节 int b; // 4字节 char c; // 1字节 };如果你按字节数相加得到6但答案是1264位系统默认对齐下。因为编译器会把a后面填充3个字节让b对齐到4字节边界c后面再填充3个字节让整个结构体大小是最大成员对齐数的整数倍。这个考点很基础但每年都有人丢分因为平时写代码不关心内存布局一旦涉及网络协议打包、共享内存设计内存对齐错误会导致严重问题。2.2 计算机网络TCP状态机是必考大头网络这块TCP就是半壁江山。三次握手、四次挥手的流程要烂熟于心但这个层面已经拉不开差距了。真正拉开差距的题目长这样为什么TIME_WAIT状态需要等待2MSL如果服务端大量出现TIME_WAIT该怎么处理这两个问题背后考的是你对TCP设计初衷的理解。TIME_WAIT等待2MSL一是为了保证最后一个ACK能到达对端如果丢了可以重传二是确保本次连接的报文段在网络中完全消失不会干扰下一个相同四元组的连接。大量TIME_WAIT常见于高并发短连接场景处理手段包括开启tcp_tw_reuse、调整tcp_max_tw_buckets、改用长连接等。再比如粘包和拆包问题选择题喜欢考简答题也喜欢考。很多人只知道要解决粘包但不理解粘包的本质是TCP是字节流协议没有消息边界所以需要应用层自己定义边界。三种主流方案要能说出来固定长度消息、分隔符、消息头中携带长度字段。如果让你设计你选哪个游戏服务器一般选第三种因为在效率和通用性之间最平衡头部4字节存长度后面跟消息体解码时先读头部就知道要读多少字节。还有epoll简直是服务器开发的灵魂考点。常考的点包括epoll和select/poll的区别、水平触发LT和边缘触发ET的区别、为什么epoll在高并发下性能更好。回答的关键在于指出select/poll每次调用都要把fd集合从用户态拷贝到内核态并且需要线性扫描全部fd才能找到就绪的而epoll通过红黑树管理fd、就绪链表记录就绪事件、epoll_wait只返回就绪的fd不用全量扫描。ET模式相比LT模式通知次数更少、效率更高但要求你一次把数据读完否则会丢数据所以实际工程里很多服务器为了简单可靠还是用LT。2.3 C语言深度智能指针与内存安全是核心考点服务器开发笔试里C相关的题目占的比重很大尤其是游戏公司。这块考的不仅仅是语法更是你对内存安全和性能的理解。智能指针是绝对高频考点。先说shared_ptr的线程安全性这个问题能刷掉一大批人。shared_ptr本身的引用计数是线程安全的但它指向的对象不是线程安全的。也就是说多个线程同时拷贝shared_ptr不会导致引用计数错乱但多个线程同时修改shared_ptr指向的对象需要你自己加锁。笔试简答题如果问你shared_ptr是否线程安全标准答法就是把这个区别说清楚。还有个经典坑shared_ptr循环引用导致内存泄漏。我见过好多次笔试题给一段代码让你分析有没有内存泄漏代码里就是两个对象互相持有shared_ptr。正确的做法是其中一边改成weak_ptr打破循环。这个知识点光背结论不行你得能画出引用计数变化的图解释为什么weak_ptr能解决这个问题——因为weak_ptr不增加引用计数它只是弱引用需要时通过lock()升级成shared_ptr。移动语义和完美转发在笔试里出现频率也在上升。选择题常考下面哪些操作会触发移动构造而不是拷贝构造。出题人最喜欢放的坑是return局部对象这是NRVO/移动语义的经典场景。而完美转发常配合模板来考核心就是std::forward和引用折叠规则。这块建议你在复习时实际写几段代码跑一跑光看书很难形成直觉。2.4 数据结构与算法不只刷题更要懂工程应用算法题在服务器开发笔试里依然要考但风格跟纯算法岗有明显区别。纯算法岗爱考难题、偏题服务器开发的算法题更接地气经常把数据结构和真实场景结合起来。LRU缓存是出现频率最高的题目之一手写LRU几乎是必考题。要求实现get和put操作时间复杂度O(1)。标准解法是哈希表双向链表。为什么是双向链表而不是单向因为删除某个节点时需要知道它的前驱节点单向链表没法O(1)完成。这个为什么经常是面试追问的点笔试时虽然不用写出来但你心里得清楚。再比如TopK问题海量数据找最大的K个数经典解法是大小为K的小顶堆。但笔试进阶版会问如果数据量大到无法全部加载进内存怎么办。这时候要答分治堆或者HashMap统计后堆排序。这种题考的不只是你会不会堆而是你有没有处理海量数据的工程直觉。还有一个容易忽视的考点是字符串处理。服务器开发里协议解析、日志分析都离不开字符串笔试里写一个高效的字符串分割函数、实现一个简单的JSON解析器这类题目每年都有。建议你平时多练练手写字符串函数不要一上来就调库因为笔试环境有时候会限制你使用某些高级API。3. 典型真题实战从读题到AC的完整思考过程3.1 网络编程题设计一个高性能定时器这是我很推荐大家认真做的一道经典题因为出题人用一道题就串起了数据结构、操作系统和网络编程三个模块。题目大概长这样请设计一个用于网络服务器的定时器支持添加定时任务、取消定时任务、检测超时并执行回调要求高效处理海量定时任务。拿到这种题千万不要上来就写代码。先明确需求网络服务器里的定时器最典型的应用场景是检测连接超时比如30秒心跳没收到就断开连接。服务器可能同时有几十万个连接每个连接一个定时器这就要求添加、删除、超时检测三个操作都要尽量高效。常见的方案有三种最小堆、时间轮、红黑树或用std::map。如果你对Linux内核够熟悉还会提到内核定时器用的就是最小堆。最小堆的优点是实现简单添加和删除是O(logN)缺点是删除任意定时器需要先找到它而堆里查找不是O(1)所以通常要配合一个哈希表存位置。时间轮的优点是添加和删除都是O(1)缺点是处理大跨度超时时间比较麻烦可能需要多层时间轮。我建议你笔试时选最小堆哈希表的方案因为思路清晰、容易写对面试官也好理解。核心代码框架大概是这样class Timer { public: int64_t expire_time; // 到期时间戳(ms) int64_t id; // 定时器ID functionvoid() callback; }; class TimerManager { private: vectorTimer heap_; // 小顶堆 unordered_mapint64_t, size_t index_; // id - 堆数组下标 public: void addTimer(int64_t expire, functionvoid() cb); void cancelTimer(int64_t id); vectorTimer getExpired(int64_t now); };这里有一个非常容易踩的坑vector扩容会导致元素的堆下标失效。因为你存的是index_[id] 下标如果vector重新分配了内存虽然下标不变但如果你把元素存成了指针就会变成悬垂指针。所以要么存下标不存指针要么写个堆模板支持在交换元素时更新反向索引。笔试时间有限你选方案时就该选自己最不容易出错的不要为了炫技写多层时间轮结果调试半天。3.2 海量数据题10亿个整数中找出不重复的数字这道题有多个变体核心思路是一样的。10亿个整数假设用int存储就是40亿字节约4GB一台普通的笔试机器内存可能只有8GB但你不能假定内存足够大出题人就是要考你在内存受限下怎么处理。思路要分几步展开。一种方案是位图法每个整数用2个bit表示状态00表示未出现01表示出现一次10表示出现多次。10亿个整数需要20亿个bit约250MB完全能装进内存。遍历一遍整数通过位操作更新对应状态最后再扫一遍位图找出状态为01的。写代码时注意位图的索引计算index num / 16offset (num % 16) * 2因为一个16bit的short可以存储8个整数的状态。如果整数范围更大或者要求内存更小可以用哈希分片把大文件切分成多个小文件比如按整数的模1024分成1024个小文件每个小文件单独统计最后合并结果。这个思路值得写一下因为它是MapReduce思想的雏形考官会认为你有处理海量数据的工程视野。这道题我特别说一句笔试时一定要先写思路再写代码。很多阅卷人先看思路思路对了哪怕代码有小bug也可能给大部分分数。反过来代码写得飞快但没写思路一旦阅卷人没看懂你的算法容易被判错。3.3 系统设计题单机IM的消息可靠投递服务器开发笔试的系统设计题通常不会让你设计一个完整的分布式系统更多是让你设计一个单机或者简单集群下能跑通的模块。我印象很深的一道题设计一个单机IM服务器的消息可靠投递机制要求消息不丢、不重接收方离线时消息暂存。这题的核心考点有三个消息确认机制、重传机制、离线消息存储。参考设计是这样的客户端A发消息给客户端B消息带全局唯一ID服务器先落库并记录状态为待确认然后推送给BB收到后回ACK服务器把状态改为已确认。如果A没收到服务器的确认超时后会重发而服务器根据消息ID去重保证不重复投递给B。B离线时消息存在数据库等B上线后按时间拉取拉取成功后再更新状态。这道题可以顺便回答TCP和UDP的选择问题。IM场景一般用TCP或者基于UDP封装的可靠协议比如QUIC就是基于UDP的可靠传输。如果你答用UDP一定要说明应用层怎么实现可靠和有序否则考官会认为你只是听说过UDP快却不知道怎么保证可靠性。我建议你在笔试时画一张简单的流程图或用文字把消息发送到接收的全链路描述清楚先把流程讲对、讲全再谈优化。因为系统设计题本质考的是你的工程思维不是考你背了多少高深组件。4. 备考路径与时间分配从零到笔试合格的实操路线4.1 复习优先级排布先保底线再冲高分秋招备考最大的问题是时间不够。很多人既想刷算法、又想补基础、还想做项目结果什么都准备了一点什么都不扎实。我给你的建议是分三轮复习每轮有明确的目标。第一轮耗时约2周主攻高频基础选择题和简答题。这个阶段的核心目标是保底线分数把计算机网络、操作系统、C语言这三个模块的基础概念吃透。每天花2小时看知识点1小时做练习题。重点覆盖TCP三次握手四次挥手、TCP vs UDP、进程线程区别、虚拟内存、智能指针、虚函数原理、内存布局。这轮结束你应该能做到任何一道基础选择题都能解释清楚选项为什么对、为什么错。第二轮耗时约2周主攻算法编程题和网络编程大题。每天至少手写2道题重点题型包括LRU、TopK、链表操作、二叉树遍历、字符串处理、动态规划入门。服务器开发的算法题整体难度低于纯算法岗考的是基础熟练度。同时把epoll、select/poll、Reactor模式、定时器实现这些网络编程大题练熟做到能默写核心框架的程度。第三轮耗时约1周刷真题和模拟题查漏补缺。这个阶段不建议再搞新知识把之前做错的题、没搞懂的概念集中过一遍。同时严格按照笔试时间做2~3套模拟题训练时间分配。我会特意练一练不会的题先跳过这个技能因为笔试最怕的就是一道题卡住后面的题目全没时间看。4.2 工具书与资料选择少而精不贪多市面上的资料太多了但真正高效的是把少数几本经典吃透。操作系统方面推荐看《深入理解计算机系统》和《现代操作系统》的关键章节前者讲虚拟内存和异常控制流非常清楚后者讲进程线程讲得透彻。网络方面《TCP/IP详解卷一》是绕不开的但不要逐页读重点看TCP协议、超时重传、连接管理这几章。《Unix网络编程》不用全看把epoll相关的章节看懂就行。C方面《Effective Modern C》和《STL源码剖析》二选一即可我更推荐前者因为2024年的笔试已经不流行考STL源码级别的细节了更看重你对现代C特性的理解。算法方面《剑指Offer》和LeetCode热题100足够了服务器开发不需要你去抠偏题怪题。资料使用的原则是每个知识点建立概念代码应用场景的铁三角笔记。比如学epoll先写下epoll和select的区别再默写一个基于epoll的简易Reactor核心代码最后标注出它的典型应用场景和坑ET模式下必须循环读直到EAGAIN。这个笔记到笔试前就是你的速查手册。4.3 项目经验怎么转化成笔试优势我经常遇到同学说我做过XX项目但笔试还是不会做。问题在于项目经验和笔试之间缺少一道翻译过程。你做过一个高并发服务器项目这个经历很值钱但你要学会把项目里的技术点翻译成笔试考点的语言。举个例子如果你的项目里用了epoll来管理多路IO那么你就应该能回答这些问题为什么用epoll而不是多线程每连接一个线程生产者和消费者模型怎么设计的怎么避免某个连接霸占CPU如果你的项目里做了连接超时管理那你就应该能画出定时器模块的结构图讲清楚时间轮和最小堆的取舍。我建议你专门花半天时间把自己项目里用到的每一个核心组件列出来然后用笔试风格去追问为什么和如果极端情况怎么办。这种转换训练比你盲目多做一个项目有效得多因为你是在把已有的经验沉淀成可复用的知识框架。4.4 时间分配兼顾学校和笔试的节奏秋招期间你大概率还在学校可能有课程、论文的压力。这时候最忌讳的是三天打鱼两天晒网。我自己的经验是保持每天固定的3小时学习时间比周末突击10小时效果好得多因为知识和知识之间的连贯性很重要断了一天再捡起来光回忆就要花掉不少时间。每周可以做一次模拟笔试找一个安静的角落按真实笔试的时间长度限制自己手机放一边。这个训练的目的不是做题而是练节奏和心态。你会发现真实笔试时最大的敌人不是题目难而是前10分钟手忙脚乱、中间卡题心态崩、最后时间不够慌着交卷。提前演练能帮你把这些问题暴露在家里而不是考场上。4.5 考前一周的冲刺清单考前一周不要再追逐新知识点了把精力放在这些事上第一把高频选择题的错题全部重做一遍确保错过的知识点不再错第二手写两遍核心代码模板包括LRU、线程池、Reactor框架、自定义内存池第三把TCP状态图完整默画一遍注意标出每个状态转移的触发条件第四对着自己的知识笔记快速过一遍遇到讲不清楚的知识点马上查资料补上。最后一天不要再做题了早点睡养足精神。笔试不仅考知识也考状态这个很多人忽略。5. 考场发挥与避坑实录5.1 笔试中那些防不胜防的坑我在改别人的笔试题时发现有些同学挂在同一个类型的坑上。第一个坑是审题不仔细。比如题目说请实现一个线程安全的单例模式很多人直接写教科书上的懒汉式加锁版本却忽略了C11以后可以用std::call_once或者函数局部static变量实现更优雅的线程安全单例。这种题考的是你知识有没有更新不是会不会背历史版本。第二个坑是多线程编程题忘记考虑竞态条件。笔试里经常给你一段多线程代码让你分析结果或找bug。很多代码乍一看没问题但仔细看会发现存在数据竞争。比如两个线程同时对一个全局变量做自增操作由于自增不是原子操作可能会丢更新。正确解法是用std::atomic或者加锁。这提醒我们在分析多线程代码时脑子里要有一个检查清单共享数据在哪有没有同步同步粒度够不够有没有死锁风险第三个坑是内存管理题里藏着悬垂指针。有一段代码函数返回了局部变量的地址或者引用了已经释放的内存问程序会发生什么。正确回答要说清楚这是未定义行为可能出现各种诡异现象不能简单地回答输出某个值。笔试里这种题考察的是你对未定义行为的敏感度。还有一个很隐蔽的坑是字节序。网络传输用的是大端序而x86机器是小端序写代码时如果不做转换解析出来的数字就是错的。笔试选择题如果在网络协议相关代码里看到数值赋值多留个心眼看看有没有字节序转换的处理。5.2 大题写不完怎么办服务器开发的笔试题量通常不小选择题简答题两三道编程大题两小时内要全部高质量完成确实很难。我的策略是先扫一遍所有题目按会做且快→会做但慢→不会做三档分类。优先把第一档的分数稳稳拿住然后做第二档不会做的题哪怕蒙也尽量写点思路上去不要空着。简答题不要小看写思路的价值。很多简答题是看要点给分的你写了关键步骤就有分。比如设计题你哪怕没有完整方案但画出了关键模块的交互流程阅卷人可能也会给一半分。编程题如果时间不够至少把核心数据结构和关键函数的思路写在注释里这样即使代码跑不通考官也能看到你的代码有逻辑。还有一个很实用的小技巧善用题目给出的类和函数签名。笔试平台通常会提供一些辅助函数或者已经定义好的数据结构顺着它们的思路往下写往往就是出题人想要的解法。不要在外面自己另起炉灶定义一套结构反而容易和给定的接口不匹配。5.3 心态与节奏把笔试当成一次技术交流我知道很多人一到笔试就紧张尤其是看到旁边人噼里啪啦敲键盘的声音就更慌了。这里分享一个有用的心态转换把笔试当成一次跟出题人的技术交流而不是一场审判。出题人设计这些题目不是为了刁难你而是想看到你怎么思考、怎么解决问题。你写思路的过程就是在跟他对话。遇到不会的题我的处理方式是先做三个深呼吸告诉自己这题不会很正常先记下来跳过去回来再收拾它。实践表明很多时候做完后面题目再回头思路反而打开了因为大脑在后台还在后台处理这个问题的信息。时间管理上我给自己定的规则是选择题平均每题不超过1分钟简答题每题不超过10分钟编程大题每题控制在25分钟以内。如果一道题超过规定时间还没突破立刻做标记跳下一题。笔试结束前留出10分钟检查重点看有没有漏答、代码有没有明显的编译错误。5.4 笔试之后复盘比成绩更重要笔试结束不是终点复盘才是提升最快的方式。我会建议你不管考得好不好都在考后第一时间把题目回忆出来哪怕记得个大题方向也行然后逐个知识点对照自己的掌握情况做标记。标记成三类完全掌握的、有点模糊的、完全不会的。对于完全不会的知识点如果它是高频考点比如TCP、epoll、线程池立刻安排时间补上因为面试环节大概率还会追着问。对于有点模糊的重新翻看资料然后自己给自己讲一遍能流畅讲出来才算过关。很多同学考完试就把题丢了然后下一场笔试继续踩同一个坑实在太可惜了。我个人还有一个习惯把每次笔试的错题整理成一个文档按知识点分类每周翻一遍。秋招季投的公司多、笔试多这个文档就是你的个性化复习资料比任何市面上的题库都更有价值。说到底笔试只是秋招这条路上的一关。它会暴露你的知识短板但也给了你一次清晰的自我诊断机会。哪怕这次没考好把坑都记下来下一次就是进步。把心态放平按照上面这些思路踏实准备我相信你能在服务器开发工程师的笔试里发挥出自己真正的水平。