今天是学习嵌入式的第38天

HTTP协议

HTTP就是跑在TCP上面的应用层协议,专门规定浏览器和服务器怎么传文本、图片这些网页资源。这里分两种模型:C/S和B/S。

C/S 客户端/服务器模型

例子:QQ、英雄联盟这种,你电脑上得单独装一个软件客户端。

✅优点:资源放你本地电脑,打开飞快;就算断网连不上服务器,很多功能照样能用。

❌缺点:

  1. 占你硬盘存储空间

  2. Windows、Mac系统不一样,开发要单独写两套代码,麻烦

  3. 服务器更新内容,你本地软件还得手动下载升级、打补丁

B/S 浏览器/服务器模型

就是咱们平时用的网页,不用装软件,打开浏览器就能访问网站。

特点:

  1. 所有图片文字资源全部存在远端服务器,不在你电脑

  2. 网站上新内容,不用你更新任何东西,服务器一改,所有人直接看到新页面

  3. 每次点开网页,都是临时从服务器下载资源到本地临时看

  4. 只要设备有浏览器就能访问,代码通用,不用单独开发客户端,省老多事

URL(统一资源定位符,就是网址)

格式:<协议>://<主机>:<端口>/<路径>

• 协议:用啥方式拿资源,常见http或者https

• 主机:服务器IP,平时咱们写域名,DNS会自动把域名翻译成IP地址

• 端口:服务器程序的门牌号!HTTP默认80或者8080,HTTPS是443

• 路径:资源在服务器硬盘里放的位置

HTTP完整传输流程(你在浏览器敲网址,背后发生啥)

  1. 浏览器输入URL网址

  2. 浏览器跟服务器IP+端口,先建立TCP连接(三次握手那套)

  3. 浏览器发送HTTP请求报文,告诉服务器我想要啥东西

  4. 服务器收到,返回HTTP响应报文,把网页数据发回来

  5. 数据传完,断开TCP连接(四次挥手)

HTTP请求报文长啥样

分三块:请求行、首部行、实体主体

  1. 请求行:方法 + URL + HTTP版本,空格隔开,结尾回车换行

◦ GET:拿服务器上的资源(比如打开网页)

◦ POST/PUT:往服务器提交数据(登录、上传表单)

  1. 首部行:一堆键值对,比如浏览器型号、编码格式,一行一组,末尾回车换行

  2. 空一行CRLF隔开,最后实体主体,GET请求一般这块是空的,POST才会放提交的数据

HTTP响应报文

同样三块:状态行、首部行、实体主体

  1. 状态行:版本 + 状态码 + 描述短语

状态码分类记这个:

1xx:通知信息,收到请求了,正在处理

2xx:成功!请求搞定

3xx:重定向,要跳转别的地址

4xx:客户端的锅,你这边请求写错了(比如404找不到页面)

5xx:服务器炸了,服务器这边出问题

  1. 首部行:和请求差不多,一堆键值对,告诉客户端文件类型、长度

  2. 实体主体:真正返回给你的网页、图片数据

TCP并发服务器模型

咱们写TCP服务器,要同时接待好多客户端,就叫并发。

  1. 多线程模型

思路:来一个客户端连接,就新开一个线程专门伺候这个客户。

优点:能实现多个人同时连服务器。

缺点:每个线程都要占独立内存栈,能开的线程数量有上限。如果几千上万客户端一起连,线程太多,系统直接崩掉。

一般搭配线程池用,提前开好一批线程,来了连接直接复用,不用反复创建销毁。

四种IO模型

  1. 阻塞IO

最省事。没有数据的时候,CPU直接把这个任务挂起歇着,完全不占CPU资源。等数据来了再唤醒。

  1. 非阻塞IO

比较浪费CPU。就算没数据,程序也不停循环、反复去问内核:"数据来了没?来了没?",疯狂轮询,CPU一直干活。

  1. 信号驱动IO(异步IO)

先告诉内核:帮我盯着这个文件描述符。一旦有事件来了,内核给我发信号通知我。我收到信号之后再来处理数据。平时程序该干嘛干嘛,不用一直等。

  1. 多路复用IO

一句话:一个线程,同时监视一堆文件描述符,哪个有事件就处理哪个。代表:select、epoll。

select

一次性放一堆fd(文件描述符)让内核帮忙盯着。只要集合里任意一个fd有读写事件,select就不再卡住,把有事件的fd留在集合里,没事件的删掉。

配套4个宏函数:

FD_ZERO:清空集合

FD_SET:把fd加入集合

FD_CLR:把fd从集合删掉

FD_ISSET:判断fd在不在集合里面

select函数参数:

nfds:所有fd里面最大的那个数字 +1

readfds:读事件集合

writefds:写事件集合

exceptfds:异常事件集合

timeout:超时时间。填NULL代表死等,一直阻塞。

返回值:成功返回有事件的fd数量;超时没事件返回0;出错返回-1。

select短板:

  1. 监听fd的数量有上限,数组大小卡死

  2. fd集合放在用户层,事件来了内核要把数据拷贝到用户空间,开销大

  3. 只能水平触发

  4. 事件来了之后,得自己循环遍历全部fd,才能找到哪个有数据,很麻烦

epoll(Linux专属,性能比select强很多!)

epoll分3个核心函数:

  1. epoll_create:创建内核里面的事件表,返回一个epoll的fd。size参数现在基本忽略。

  2. epoll_ctl:操作epoll事件表,可以增、改、删监听的fd事件

EPOLL_CTL_ADD:添加fd进事件表

EPOLL_CTL_MOD:修改已经监听的事件

EPOLL_CTL_DEL:删掉fd

事件类型:EPOLL_IN 可读、EPOLL_OUT可写、EPOLLET开启边沿触发

  1. epoll_wait:蹲事件,阻塞等待,有事件就把触发事件的fd打包返回给用户。

timeout=-1就是一直死等。返回值是触发事件的fd个数,失败返回-1,超时返回0。

epoll牛逼在哪:

  1. 监听fd数量几乎没有上限,百万连接都扛得住

  2. 事件表放在内核里面,不用来回拷贝大量数据,省资源

  3. 支持水平触发,还支持高速的边沿触发EPOLLET

  4. 内核直接把发生事件的fd挑好给你,不用自己遍历全部fd,速度起飞

相关推荐
DYWorker0011 小时前
Linux驱动子系统:中断子系统 —— Consumer和Provider(005)
linux·驱动开发
草莓熊Lotso1 小时前
【Redis 进阶】主从复制深度解析:从配置落地到 PSYNC 同步原理
linux·开发语言·网络·数据库·redis·缓存·php
传奇开心果编程1 小时前
【Rust入门知识点学与练】第33课:异步编程入门(async/await)强化
开发语言·学习·rust
传奇开心果编程1 小时前
【Rust入门知识点学与练】第34课:所有权与借用
开发语言·学习·rust
Zane19941 小时前
冒泡、选择、插入排序都是O(n²),希尔排序凭什么说自己能更快
算法·排序算法
ShineWinsu1 小时前
对于Git:远程操作的超详细保姆级解析
linux·git·gitee·github·远程仓库·分布式版本控制系统·远程操作
小张成长计划..2 小时前
【Linux】21:进程间通信
linux
AAA代码批发商2 小时前
DAY43 ARM 体系结构学习笔记|嵌入式入门,从硬件组件到流水线、内存与栈帧
arm开发·笔记·学习
彧azz2 小时前
初学Unity:编辑器
笔记·学习·unity·游戏引擎