最近学习了网络编程中的HTTP协议和TCP并发服务器,在开始新内容之前,先回顾上节课学的TCP与UDP通信,把基础捋清楚。
一、TCP 和 UDP 的区别
两者都是传输层协议,但是设计思路完全不一样:
UDP
实现机制简单,资源开销小;无连接,发送数据之前不需要建立连接;但是不安全不可靠,不保证数据一定到达,也不保证顺序。适合视频通话、直播这类允许少量丢包的场景。
TCP
实现机制复杂,资源开销更大;面向连接,通信前必须完成三次握手建立连接;提供可靠传输,会做重传、拥塞控制,保证数据完整有序到达。我们接下来要学习的HTTP协议就是跑在TCP之上。
简单来说,UDP快、轻、不可靠;TCP稳、重、可靠。
二、HTTP协议
HTTP是超文本传输协议,属于应用层协议,基于TCP实现,规定了超文本在网络中的传输流程。
C/S模型和B/S模型
-
C/S(客户端/服务器)模型
优点:资源存放在本地,加载速度快;不需要连接服务器,本地就可以运行。
缺点:占用本地存储空间;不同平台需要单独编写客户端代码;资源更新需要本地升级或者打补丁。
-
B/S(浏览器/服务器)模型
特点:资源全部保存在服务器;新增资源不需要更新本地;每次访问都从服务器下载最新资源;只要有浏览器就可以访问,代码可以跨平台复用,不用重复开发客户端。
URL统一资源定位符
格式:协议://<主机>:<端口>/<路径>
协议:http或者https,用来指定访问资源的方式
主机:服务器IP地址,日常使用一般是域名,由DNS完成域名到IP的转换
端口:服务程序端口,HTTP默认80/8080,HTTPS默认443
路径:资源在服务器上存放的位置
HTTP完整传输流程
-
浏览器输入URL
-
浏览器向对应IP和端口发起TCP连接
-
发送HTTP请求报文
-
服务器回复HTTP响应报文
-
断开TCP连接
HTTP报文格式
请求报文
由请求行、首部行、空行、实体主体组成。
请求行:方法 URL 版本,常见方法GET用于获取资源,POST/PUT用于向服务器提交数据。
首部行:字段名:值,每一行以回车换行结束。
空行:CRLF,用来分隔首部和实体主体。
响应报文
由状态行、首部行、空行、实体主体组成。
状态行:版本 状态码 短语
状态码分类:
1xx:通知信息,请求收到正在处理
2xx:请求成功
3xx:重定向,需要进一步操作
4xx:客户端错误,请求语法出错
5xx:服务器端错误,服务端无法完成请求
三、TCP并发服务器模型
多线程模型
多线程可以解决TCP并发问题。但每个线程都占用独立栈空间,能够创建的线程数量有限。如果并发客户端数量过大,系统存在崩溃风险,实际开发一般搭配线程池使用。
1、四种IO模型
-
阻塞IO:没有数据时,CPU将任务挂起,不占用CPU资源,效率高。我们基础socket编程大多使用阻塞IO。
-
非阻塞IO:没有数据时,CPU依然会循环轮询检查数据是否到来,会消耗CPU。
-
信号驱动IO(异步IO):把文件描述符设置为异步IO,内核监测事件,事件发生后发送信号通知用户层处理。
-
多路复用IO:select、epoll,用来同时监听大量文件描述符。
2、select
select可以监听一组文件描述符集合,当集合中至少一个fd产生事件,select就会返回。
配套宏函数:
FD_CLR:清除集合中的fd
FD_ISSET:判断fd是否还在集合
FD_SET:把fd加入集合
FD_ZERO:清空集合
select函数监听fd集合,返回就绪fd数量;超时参数设置为NULL代表阻塞等待。
缺点:fd数量存在上限;fd集合在用户空间,每次需要拷贝;仅支持水平触发;需要手动遍历找出就绪fd。
3、epoll
epoll是Linux下高性能多路复用方案,三个核心接口:
-
epoll_create:创建epoll内核事件表,返回epoll文件描述符。
-
epoll_ctl:操作事件表,支持ADD添加、MOD修改、DEL删除事件。
-
epoll_wait:等待事件发生,返回就绪事件的数量。
epoll支持水平触发和边沿触发,默认水平触发。
4、select与epoll对比
select
-
监听fd集合是数组,存在数量上限
-
fd集合位于用户空间,事件发生需要拷贝,资源开销大
-
只支持水平触发
-
需要手动遍历查找就绪fd
epoll
-
监听事件表在内核中,没有fd数量上限
-
无需频繁拷贝用户态内核态数据,开销小
-
支持水平触发、边沿触发两种模式
-
直接返回就绪的fd,不需要遍历全部集合
网络编程的底层逻辑,就是通过socket进行数据收发,面对大量并发连接,就需要借助多路复用IO提升服务器处理能力。TCP/UDP是底层传输基础,HTTP是上层应用协议,把这些知识点串联起来,才能理解完整的网络通信过程。