1.你的服务器解析 HTTP 报文的时候,怎么区分报头和正文?
读到连续\r\n\r\n,代表报头结束,后面根据 Content-Length 读取对应长度的正文。
2.Content-Length 作用?
标记请求正文的字节数,用来解决 TCP 粘包,确定读到哪里结束。
3.TCP报文是什么样的?
HTTP 请求报文由 4 部分组成:请求行、请求报头、空行、请求正文,空行用来分隔报头与正文。
①请求行(报文第一行) 格式:请求方法 + URI + HTTP 版本 + \r\n 作用:说明本次请求的操作类型、访问资源路径、使用的 HTTP 协议版本。 例:GET /index.html HTTP/1.1
②请求报头(多行键值对) 格式:Key: Value\r\n,可以有多行。 作用:传递请求附加信息。 常见:Host(目标地址端口)、Connection(keep-alive 长连接)、Content-Length(正文字节长度)、User-Agent(客户端标识)。
③空行 单独的\r\n,标志请求报头结束。必须有,用来分割报头和请求正文。
④请求正文(可选) 客户端提交的业务数据。
- GET:一般不带正文;
- POST/PUT:携带正文,例如表单、JSON。 服务器依靠
Content-Length获取正文长度,用来处理 TCP 粘包,确定读取多少字节。
3.解析响应报文和请求报文最大的难点差别?
| 部分 | Request(请求) | Response(响应) |
|---|---|---|
| 首行 | 请求方法、URI、HTTP 版本 | HTTP 版本、状态码、状态描述 |
| 报头 | 客户端的附加信息 | 响应资源的附加信息 |
| 正文 | 客户端上传数据(可选) | 服务器返回资源(可选) |
解析请求要解析 URI、请求方法;解析响应首先解析状态码,报头和正文的解析逻辑是同一套。
4.C++ 读取文件三种方式对比表
| 对比维度 | std::ifstream(C++ 流) | fopen/fread/fclose(C 库) | open/read/close(Linux 系统调用) |
|---|---|---|---|
| 所属层级 | C++ 标准库封装 | C 标准库封装 | 操作系统原生 API |
| RAII 自动关闭 | ✅ 是,对象析构自动 close | ❌ 否,必须手动 fclose | ❌ 否,必须手动 close |
| 跨平台 | ✅ Linux/Windows 均可 | ✅ 跨平台 | ❌ 仅 Linux/Unix |
| 缓冲区 | 自带流缓冲区 | 自带 stdio 缓冲区 | 无缓冲,直接系统调用 |
| 类型安全 | ✅ 类型安全 | ❌ void*,需手动转换 | ❌ int fd,错误码手动判断 |
| 性能 | 有一层封装,略低 | 略高于 ifstream | 最高,几乎无封装 |
| 精细控制 | 一般 | 一般 | ✅ 可设置 O_NONBLOCK 等 |
| 与 string 配合 | ✅ 友好 | 需 char * 手动转换 | 需 char * 手动管理 |
| 适用场景 | 应用层业务代码、配置 / 网页读取 | 老 C 项目、简单读写 | 高性能 IO、非阻塞网络编程 |
5.std::smatch的作用
std::smatch 是 C++ 正则库的匹配结果对象,用来保存正则表达式捕获出来的子串。 一般和 regex_match 一起使用,_matches[0]是完整匹配内容,下标 1、2 对应各个括号分组捕获的内容。在我的 HTTP 服务器项目中,用来解析请求行,提取请求方法、URI、协议版本。
7.搜索二叉树和红黑树的区别?

8.URL和URI的区别

这个位置是URI,是URL的一部分,比如https://mp.csdn.net/mp_blog/creation/editor?spm=1001.2014.3001.4503 这个就是一个URL,而URI是edlitor?spm-1001,2014,3001这个

9.http响应的重定向字段的含义
重定向就是服务器返回 301/302 状态码,告诉浏览器去访问 Location 里的新地址,浏览器自动发起第二次 HTTP 请求。 _redirect_flag是布尔标记,用来标记本次响应是否需要执行重定向;如果标记为 true,就组装重定向响应,而不是返回文件内容。

10.开发muduo库的时候遇到的问题以及解决方法
S:手写 HTTP 服务器,状态机解析请求行,做超长请求防护。
T:防止超长请求攻击。
A:我写了代码,读不到完整一行时,判断缓冲区可读大小超过 MAX_LINE 返回 414。
后面测试发现防护存在漏洞:攻击者缓慢发送字符,不发送\r\n换行,缓冲区维持在 MAX_LINE 以内,持续占用 fd,造成慢速 DoS。 一开始我想把 MAX_LINE 调小,更早触发上限,但是测试发现这只是缓解,治标不治本。攻击者依旧可以一字节一字节慢慢发送,缓冲区永远达不到阈值。 所以我意识到,单纯靠缓冲区长度限制无法解决。
最终方案: ① 每次 socket 读取数据后都执行缓冲区长度校验;
② 使用项目里的时间轮定时器,给每个连接注册空闲超时任务;长时间收不到完整请求,直接关闭 fd 释放资源。 R:修复之后,既能正常处理 TCP 分包带来的半行数据,又可以抵御慢速 DoS 攻击。

11.什么是状态机?

12.http搭建遇到的问题总结



13.关于muduo库的线程安全问题
Muduo 每个 EventLoop 都有独立私有的任务队列 ,不存在所有 EventLoop 共用同一个全局任务池。 别的线程通过 runInLoop 向这个 loop 投递任务时,队列本身带互斥锁保护,push 操作线程安全。 但是任务回调内部访问的业务数据,muduo 不会自动加锁,业务数据的并发访问需要我们自己保证线程安全。