C++求职LinuxWebServer面试篇(响应Http请求报文)

⭐️我叫忆_恒心,一名喜欢书写博客的研究生👨‍🎓。
如果觉得本文能帮到您,麻烦点个赞👍呗!

近期会不断在专栏里进行更新讲解博客~~~
有什么问题的小伙伴 欢迎留言提问欧,喜欢的小伙伴给个三连支持一下呗。👍⭐️❤️
📂Qt5.9专栏定期更新Qt的一些项目Demo
📂C++ Linux Web Server笔记整理 定期更新关于Linux Web服务器最新面试知识!堪称全网最全!
📂项目与比赛专栏定期更新比赛的一些心得面试项目常被问到的知识点。
关于专栏的任何问题,欢迎私作者或者评论中提问看到后会立马回复
欢迎评论 💬点赞👍🏻 收藏 ⭐️加关注+
✍🏻文末可以进行资料和源码获取欧😄

已经更新的文章:
https://ydlin.blog.csdn.net/article/details/141302125

前言

秋招又开始了,最近陆陆续续有很多学弟学妹私信我分享学习和面试的资料,因此我打算通过LinuxWebServer项目,以项目的方式串联起面试期间高频的知识点。

现在的八股文真是满天飞,很多你看完后没去用也无法理解,面试官一深追就容易露馅。因此我想整理一篇以项目为切入点的面经指南。

C++求职LinuxWebServer面试篇 打牢编程基础,快速掌握面试要点,短时间内让你熟悉C++开发项目中,计算机网络和操作系统的重要意义。

这绝对是全文少有深度解析LinuxWebServer项目的文章,让你更加深入的了解这个项目,并且以此为契机,好好梳理自己的知识。C++求职LinuxWebServer面试篇 如果你能吃透,面试绝对是一大加分项。相比于其他直接开背的八股文,我更想分享如何将知识融汇贯通, 找工作的过程是痛苦的,秋招更是如此,但是也是进步最快的一段时光。
在这里插入图片描述
一路走来,磕磕绊绊,但终有收获。

对于每个普通人而言,请记住,我们执着于长跑中胜出。

最后祝大家都能顺顺利利的上岸!

大家一起加油呀,跟大家分享一下那段时间面试过程中,收获和所得。真心建议从前言开始看欧。

2024/8/17

全文一共近两万字,基于LinuxWebServer面试篇V0.1版本,已经整理完啦。还要很多细节待补充,后面也会不断补充进去。如果觉得有帮助的话。😃帮忙点赞、收藏、转发。⭐️👍↪️转发。

C++求职LinuxWebServer面试篇(前言)

C++求职LinuxWebServer面试篇(项目介绍)

C++求职LinuxWebServer面试篇(Http请求与处理

C++求职LinuxWebServer面试篇(如何处理Http请求)

如何响应收到HTTP请求的报文

在这里插入图片描述

http响应报文处理流程

当上述报文解析完成后,服务器子线程调用process_write完成响应报文,响应报文包括

1.状态行:http/1.1 状态码 状态消息;

2.消息报头,内部调用add_content_length和add_linger函数

	l content-length记录响应报文长度,用于浏览器端判断服务器是否发送完数据
	
	l connection记录连接状态,用于告诉浏览器端保持长连接

3.空行

4. 响应正文

随后注册epollout事件。服务器主线程检测写事件,并调用http_conn::write函数将响应报文发送给浏览器端。至此整个http请求和响应全部完成。

1 主从状态机的模式

主状态机
请求行解析完毕
请求头解析完毕
消息体解析完毕
CHECK_STATE_REQUESTLINE
CHECK_STATE_HEADER
CHECK_STATE_CONTENT
从状态机
语法错误
行不完整
行完整
LINE_OK
LINE_BAD
LINE_OPEN

在这里插入图片描述

主状态机

三种状态,标识解析位置。

  • CHECK_STATE_REQUESTLINE,解析请求行
  • CHECK_STATE_HEADER,解析请求头
  • CHECK_STATE_CONTENT,解析消息体,仅用于解析POST请求
从状态机

三种状态,标识解析一行的读取状态。

  • LINE_OK,完整读取一行
  • LINE_BAD,报文语法有误
  • LINE_OPEN,读取的行不完整
void http_conn::process() {
    HTTP_CODE read_ret = process_read();
    if(read_ret == NO_REQUEST) {
        modfd(m_epollfd, m_sockfd, EPOLLIN);
        return;
    }
    bool write_ret = process_write(read_ret);
    if(!write_ret)
        close_conn();
    modfd(m_epollfd, m_sockfd, EPOLLOUT);
}

HTTP请求报文:请求行(request line)、请求头部(header)、空行和请求数据

响应报文:状态行、消息报头、空行和响应正文。

2 GET和POST的区别

  • 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制。(大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。
  • GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100(指示信息—表示请求已接收,继续处理)continue,浏览器再发送data,服务器响应200 ok(返回数据)。

3 HTTP 状态码

  • 1xx:指示信息–表示请求已接收,继续处理。
  • 2xx:成功–表示请求正常处理完毕。
    • 200 OK:客户端请求被正常处理。
    • 206 Partial content:客户端进行了范围请求。
  • 3xx:重定向–要完成请求必须进行更进一步的操作。
    • 301 Moved Permanently:永久重定向,该资源已被永久移动到新位置,将来任何对该资源的访问都要使用本响应返回的若干个URI之一。
    • 302 Found:临时重定向,请求的资源现在临时从不同的URI中获得。
  • 4xx:客户端错误–请求有语法错误,服务器无法处理请求。
    • 400 Bad Request:请求报文存在语法错误。
    • 403 Forbidden:请求被服务器拒绝。
    • 404 Not Found:请求不存在,服务器上找不到请求的资源。
  • 5xx:服务器端错误–服务器处理请求出错。
    • 500 Internal Server Error:服务器在执行请求时出现错误。

4 你的项目http请求怎么做的?如何保证http请求完整解析

该项目使用线程池(半同步半反应堆模式)并发处理用户请求,主线程负责读写,工作线程(线程池中的线程)负责处理逻辑(HTTP请求报文的解析等等)

在HTTP报文中,每一行的数据由\r\n作为结束字符,空行则是仅仅是字符\r\n。因此,可以通过查找\r\n将报文拆解成单独的行进行解析,项目中便是利用了这一点。

主从状态机可以保证完整解析。

具体来说:

  • (存储读取的请求报文数据)判断当前字节是否为\r

    • 接下来的字符是\n,将\r\n修改成\0\0,将m_checked_idx指向下一行的开头,则返回LINE_OK
    • 接下来达到了buffer末尾,表示buffer还需要继续接收,返回LINE_OPEN
    • 否则,表示语法错误,返回LINE_BAD
  • 当前字节不是\r,判断是否是\n(一般是上次读取到\r就到了buffer末尾,没有接收完整,再次接收时会出现这种情况

    • 如果前一个字符是\r,则将\r\n修改成\0\0,将m_checked_idx指向下一行的开头,则返回LINE_OK
  • 当前字节既不是\r,也不是\n

    • 表示接收不完整,需要继续接收,返回LINE_OPEN

如何响应

在这里插入图片描述

思考

为什么要用状态机?

传统的控制流程都是按照顺序执行的,状态机能处理任意顺序的事件,并能提供有意义的响应—即使这些时间发生的顺序和预计的不同。

有没有想过状态机会给项目带来哪些危害?

缺点:状态机的缺点就是性能比较低,一般一个状态做一个事情,性能比较差,在追求高性能的场景下一般不用,高性能场景一般使用流水线设计。

项目中使用主从状态机的模式进行解析,从状态机(parse_line)负责读取报文的一行,主状态机负责对该行数据进行解析,主状态机内部调用从状态机,从状态机驱动主状态机。每解析一部分都会将整个请求的m_check_state状态改变,状态机也就是根据这个状态来进行不同部分的解析跳转的:

往期优秀文章推荐:

  1. 研究生入门工具——让你事半功倍的SCI、EI论文写作神器
  2. 磕磕绊绊的双非硕秋招之路小结
  3. 研一学习笔记-小白NLP入门学习笔记
  4. C++ LinuxWebServer 2万7千字的面经长文(上)
  5. C++Qt5.9学习笔记-事件1.5W字总结

资料、源码获取以及更多粉丝福利,可以关注下方进行获取欧
推荐

### C++ WebServer 面试常见问题及经验分享 #### 常见技术知识点 C++ WebServer 的开发涉及多个核心技术领域,以下是常见的面试考察方向及其相关内容: 1. **Socket 编程** Socket 是网络通信的基础,在实现 WebServer 时必不可少。通常会问到如何创建套接字、绑定地址、监听连接以及数据传输的过程[^3]。 2. **IO 多路复用** IO 多路复用机制(如 `select`、`poll` 和 `epoll`)用于提高服务器处理并发请求的能力。需要理解这些方法的区别和适用场景,并能解释为什么现代高性能服务倾向于使用 `epoll`。 3. **线程池与任务队列** 线程池可以有效管理资源并提升性能。需掌握其设计原理,包括线程的初始化、销毁策略,以及任务分配逻辑。同时要熟悉任务队列的设计方式及其在高并发环境下的优化手段。 4. **内存管理** 在 C++ 中手动管理内存是一项挑战。可能被询问关于智能指针的应用 (`std::shared_ptr`, `std::unique_ptr`) ,RAII (Resource Acquisition Is Initialization) 模式的实践意义等话题[^2]。 5. **异常处理** 掌握标准库中的异常类体系结构非常重要;另外还需要知道自定义异常类型的最佳做法,确保程序健壮性和可维护性。 6. **MVC 架构模式** 尽管 MVC 更常应用于 Java 或 PHP 开发中,但在某些情况下也可能适用于基于 C++ 实现的服务端应用。应能够阐述 Model、View 和 Controller 各部分职责划分原则[^4]。 7. **安全性考量** 对于任何 web 应用而言安全都是不可忽视的一环。候选人应该展示自己对于防止 SQL 注入攻击、XSS 攻击等方的知识水平[^5]。 8. **负载均衡与一致性哈希算法** 当扩展至分布式系统架构下运行时,则涉及到客户端请求分发给不同节点上的实例这一过程所采用的技术方案——比如 LVS/Nginx 这样的代理层配合特定散列函数来决定目标机器位置等问题都需要有所准备。 #### 经验建议 - 准备过程中不仅要记忆理论知识,更要通过实际动手构建小型项目加深印象。 - 参考经典书籍如《剑指 Offer》,它提供了大量针对计算机科学基础概念的实际编码练习机会。 - 学习调试技巧同样重要,因为即使是最优秀的开发者也会遇到难以预料的问题情境。因此熟练运用 gdb 工具或者 IDE 内置功能进行错误定位变得尤为关键。 ```cpp // 示例代码片段:简单的 TCP Server 使用 epoll #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <fcntl.h> int main() { int listen_fd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serv_addr; memset(&serv_addr, '0', sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(8080); bind(listen_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); listen(listen_fd, 1024); // 设置为非阻塞模式 fcntl(listen_fd, F_SETFL, O_NONBLOCK); // 初始化 epoll int epfd = epoll_create(1); struct epoll_event ev, events[20]; ev.events = EPOLLIN | EPOLLET; // 边缘触发 ev.data.fd = listen_fd; epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &ev); while(true){ int nfds = epoll_wait(epfd, events, 20, -1); for(int i=0;i<nfds;++i){ if(events[i].data.fd == listen_fd){ accept_new_connection(); }else{ handle_client_data(); } } } close(listen_fd); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忆_恒心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值