当前位置: 首页 > article >正文

webserver的http实现

1、用了状态机,为什么要用状态机?
在逻辑处理模块中,响应的http请求采用主从状态机完成,
传统的控制流程都是按照顺序执行的,状态机能够处理任意顺序的事件,并能提供有意义的响应--即使这些事件发生的顺序和预计的不同。
项目中使用主从状态机的模式进行解析, 从状态机负责读取报文的一行,主状态机负责对该行数据进行解析,主状态机内部调用从状态机,从状态机驱动主状态机。
每解析一部分都会将整个请求的check_state状态改变,状态机也就是根据这个状态来进行不同部分的解析跳转的。
2、状态机的转移图画一下
1、主状态机的三种状态,标志解析位置
    REQUESTLINE,解析请求行
    HEADER,解析请求头
    BODY,解析消息体,仅用于解析POST请求
2、从状态机的状态,标识解析一行的读取状态
    ParseRequestLine,完整读取一行,该条件涉及解析请求行和请求头部
    ParseHeader,报文语法有误
   ParseBody,读取的行不完整
3、处理结果
NO_REQUEST:请求不完整,需要继续读取请求报文数据
GET_REQUEST 获得了完整的HTTP请求
BAD_REQUEST HTTP请求报文有语法错误
INTERNAL_ERROR 服务器内部错误
3、状态机的缺点是什么?
状态机的缺点就是 性能比较低 ,一般一个状态做一个事情,性能比较差,在追求高性能的场景下一般不用,高性能场景一般使用 流水线设计。
4、get和post的区别
get主要用来获取数据,而post是提交或修改数据;
get有长度限制(2048字节)而post没有;
get的参数是显式的,get的参数会附加在url之 中,以 “ ? “分割url和传输数据,多个参数用 “&”连接;而post是隐式的,post是放在请求体中;
get请求会保存在浏览器历史记录中,也可以保存在web服务器日志中;
get在浏览器回退时是无害的,而post会再次提交请求;
get请求只能进行url编码,而post支持多种编码方式;
get请求的参数数据类型只接受ASCII字符,而post没有限制。
5、http请求怎么拆包?
HTTP请求内容:请求行,请求头,空行,请求体
一个有报文的请求到服务器时,请求头里都会有content_length,这个指定了报文的大小。报文如果很大的时候,会通过一部分一部分的发送请求,直到结束。当这个过程中,出现多个请求,第一个请求会带有请求头信息,前面一个请求的发送的报文如果没有满时,会把后面一个请求的内容填上,这个操作就叫 粘包 。这样粘包后, 它会通过content_length字段的大小,来做拆包。
在post发送大数据量时会分段发,接收端一次接收的只是部分post, 源代码读到len=-1直接开始处理了 ,但实际上还有数据没发过来,在process内判断buffer收到的len和header中的content-length是否匹配,如果不匹配直接返回false,下一个post包发过来接着用buffer收,最后收完了再开始request处理。
6、HTTP的整体流程
浏览器发出http连接请求,主线程创建http对象接收请求同时将所有数据存到对应的buffer,将该对象插入任务队列,工作线程从任务队列中取出一个任务进行处理。
工作线程取出任务后,调用process_read函数,通过主从状态机对请求报文进行解析。
解析完成后,跳转do_request函数生成响应报文,通过process_write写入buffer,返回给浏览器端。
注意:在生成的响应报文中并没有返回消息的具体内容,文件也并不在缓冲区,因此传输的时候采取分块写的方式,一块传输buff里面的内容,另一块传输内存映射的文件指针。
7、报文解析的整体流程
1、利用search从缓冲区读取响应的报文片段。
2、建立请求报文的有限状态机,请求报文中一般包含post和get。该有限状态机的作用原理在于每次读取缓冲区中的一行进行匹配,直到状态变为finish。
REQUEST_LINE——ParseRequestLine_(line)
HEADERS——ParseHeader_(line)
BODY——ParseBody_(line)
调用ParsePost();,因为只有post中有请求体
1. 解析 POST 请求 :检查请求方法和  Content-Type  是否符合条件。
2. 解析表单数据 :从 URL 编码的请求体中提取用户提交的数据。
cpp /*URL 编码 是一种用于将数据编码为有效 URL 字符串的方式,其中特殊字符(如空格、&、= 等)会被替换为特定的字符序列: *空格编码为 %20 *特殊字符(如 &, =)不会直接出现在值中,而需要进行编码 *其他特殊字符也会有类似的编码方式,如 %3A 表示冒号 :
3. 路径判断 :检查路径是否是需要处理的特定页面(如登录或注册页面)。
4. 登录或注册逻辑 :根据路径进行用户验证,判断是登录还是注册,并根据结果决定跳转的页面。
8、报文响应的流程(httpresponse):
httprequest是对读取缓冲区中的可读数据进行解析,
httpresponse是对缓冲区中的可写数据进行写入。
响应报文的四个部分:
9、buffer缓冲区总结:

http://www.kler.cn/a/464791.html

相关文章:

  • 145页PPT智慧矿山整体规划建设方案
  • 【微信小程序获取用户手机号
  • 《Swift 结构体》
  • CSS——1.优缺点
  • vite-plugin-imagemin安装问题
  • 现代光学基础4
  • MATLAB中whitespacePattern函数用法
  • maya 删除 Ctrl + Delete vs Delete
  • Python实现Excel行列转换
  • 算法 class 005 (对数器C语言实现)
  • 第一次作业
  • Java项目常见基础问题汇总(6)
  • 基于Golang的网络安全靶场设计与实现
  • 利用深度学习进行系统健康监控:智能运维的新纪元
  • Vue 中el-table-column 进行循环,页面没渲染成功
  • 并联带阻滤波器带通滤波器对幅值和相位的影响(IIR)
  • C++ 设计模式:组合模式(Composite Pattern)
  • QT----------多媒体
  • HarmonyOS Next ArkUI @State @Prop @Link @Provide @Consume笔记
  • EasyExcel简介和读写操作
  • IoC设计模式详解:控制反转的核心思想
  • PyTorch 中 coalesce() 函数详解与应用示例
  • Linux之ARM(MX6U)裸机篇----6.BSP工程管理实验
  • Vue 自定义指令
  • 全国知名网络安全赛事西湖论剑·杭州网络安全技能大赛启动报名
  • 【C++/CMake】从静态库到动态库:一行改动解决 “找不到 -ljsoncpp” 链接报错