http协议
前一阵子跟着宋红康老师学了一遍 jvm, 收获颇深. 因为追求看视频的速度问题所以没有去做笔记. 后期回忆起来可能记忆犹如无根浮萍一般. 所以以后还是打算能记笔记就记笔记.
http tcp udp 什么的, 其实学过很多了遍. 就计算机网络来说, 本科学了一遍, 选修课刷 GPA 又选修了一遍, 研究生又学了一遍. 可以说是学了三遍了. 但是现在回想起来, 框架还在, 但是具体的细节比如 tcp 滑动窗口之类的还是忘记了, 还是要经常回忆复习的好.
网络分层
复杂的网络
由于网络环境来说, 会有数据丢包, 数据重复, 完整性校验, 信号衰减等等问题.
为了处理这种问题, 国际标准组织对于整个网络体系进行了分层, 同时也规定了每一层的交互规则. 为了解耦与可拓展性(这里其实类似于 Java 中的接口的作用)
分层方法
两种分层方法: OSI 和 TCP/IP
一个 http 请求的分层解析流程
- 在浏览器输入域名回车
- 域名解析
- 为什么解析? 网络中两端进行交互只认 ip 地址
- 首先查浏览器有没有这个 DNS 的缓存
- 如果没有去计算机本地 host 文件查看
- 如果没有, 发起 DNS 请求
- DNS 也是服务器, 也有自己的 IP 地址, 是配在操作系统的
- DNS 是使用 UDP 协议的, 传输层会加一个 UDP 请求头
- DNS 有时候会用 TCP, 如果相应的内容超过 512 字节, 或者使用区域传送
- 加一个网络层 IP 请求头
- 传送到数据链路层, 数据链路层加上自己的头, 并且加入下个机器的 MAC 地址(从网络层的 ARP 协议而来https://blog.csdn.net/ever_peng/article/details/80008638)
- 传送到路由器上面
- 路由器是三层的(网络,数据链路,物理层), 不同于交换机(物理,数据链路)
- 路由器解析刚才收到的消息
- 从物理层开始
- 数据链路层会查看 MAC 地址是否给与, 是的话交给网络层
- 网络层查看数据应该传送的下一个路由器是多少, 这里一般是传送到服务商的路由器
- 运营商解析地址并返回 DNS 信息
- 返回到路由器, 从网络层解析到物理层
- 返回到计算机
- 从物理层开始
- 检查 IP 头(网络层)
- 检查UDP协议头(传输层)
- DNS 拿到信息(应用层)
- 根据 DNS 获取的信息, 发送 http 协议
- 开始类似上面逐层加协议头
- 发送到路由器
- 路由器发送到运营商ISP找到目标服务器
- 到达目标服务器
- 物理层
- 数据链路层解析
- 网络层解析
- 传输层解析, 这一层会解析端口, 比如 80
- 应用层解析, 交给对应端口的应用程序
- 应用程序构造一个 http 的响应报文回传
- 收到目标服务器的回传报文
- 这里依然是逐层的
==上面写的有点长, 其实脑海里在思考 http 协议交流过程的时候, 只需要建立两个塔状的模型, 一个是源计算机, 一个是目标计算机, 所有的交流都是从一方最高到对方最高. 牢记这一点即可==
HTTP协议
HyperText Transfer Protocol
五大特点
- 支持 c/s 模式
- 简单快速
- 灵活
- 无连接: 限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- 因为HTTP诞生之初,主要是为了应付容易很小的文本传输,所以即使这样也没多大的问题
- 为了解决TCP连接问题, HTTP1.1提出了持久连接
- 所以说这个无连接其实算是过去式
- 无状态: HTTP协议无法根据之前的状态进行本次的请求处理
- 为了解决无状态, 引入cookie技术
说白了五大特点简直是人硬凑的, 不过也是有时代因素吧, 现在看来只需要记住后面两个就可以了:
==无连接, 无状态==
注意: 无连接是应用层面上的无连接! 要从应用层去理解
HTTP报文格式
- 起始行(请求行)
- 请求: GET /index.html HTTP/1.1
- 构成: METHOD+空格+URI+空格+VERSION+换行
- 返回: HTTP/1.1 200 OK
- 构成: VERSION+空格+STATUS CODE+空格+REASON+换行
- 请求: GET /index.html HTTP/1.1
- 头部字段集合
- Connection: keep-alive
- …
- 空行
- 消息正文
http协议还有很多, 暂时先跳过
TCP协议
Transmission Control Protocol
面向连接的, 可靠的, 基于字节流的传输层通信协议
特点
- 基于连接的: 数据传输之前都要建立连接
- 全双工: 双向传输
- 字节流: 不限制数据大小, 打包成报文段, 保证有序接收, 重复报文自动丢弃
- 因为网络,数据到达很可能乱序, 接收端需要重排序
- 给到应用层肯定是排序后的
- 流量缓冲: 解决双方处理能力的不匹配
- 可靠的传输服务: 保证可达, 丢包时通过数据重发机制实现可靠性
- 拥塞控制: 防止网络出现恶心拥塞
TCP连接
四元组: 源地址, 源端口, 目的地址, 目的端口
三次握手
一个小的知识点: 为什么ack是x+1呢?
官方的回答是:
The server responds to the client with a sequence number of zero, as this is its first packet in this TCP session, and a relative acknowledgement number of 1. The acknowledgement number is set to 1 to indicate the receipt of the client’s SYN flag in packet #1.
Notice that the acknowledgement number has been increased by 1 although no payload data has yet been sent by the client. This is because the presence of the SYN or FIN flag in a received packet triggers an increase of 1 in the sequence. (This does not interfere with the accounting of payload data, because packets with the SYN or FIN flag set do not carry a payload.)
也就是由于SYN或者FIN标志位的存在,造成了sequence的增加.
- +1是针对SYN和FYN的,主要是在没有数据传输的情况下,告诉发送端我收到了你之前发的这俩标示(的其中一个)
- 这个+1是基于对方的seq来加的
感谢这篇文章的参考:https://blog.csdn.net/oldfish_C/article/details/105150516
- linux可以通过`netstat -来查看tcp连接的状态
- 可以通过
telnet [ip] [port]
建立tcp连接
四次挥手
两端都可以关闭连接, 在此将主动关闭的称为client
图中的M和N和上面图中x和y是一样的含义, 只是因为分开画的表示不一样.
- server在close_wait阶段仍然可以发数据, 发送结束后发送FIN
- client time_wait阶段等待一个来回的时间(2MSL)==面试高频==
- 防止滞留在网络中的报文, 对新建立的连接造成数据扰乱(确保close_wait阶段的内容被收到)
- 防止报文丢失(也就是图中最后一个ACK), 导致server重复发送FIN
字节流的协议
- TCP把应用层的数据看成一连串的无结构的字节流; 数据将会被切割成小报文; TCP根据报文的序列号进行排序
- TCP并不知道字节流的含义
- TCP并不关心应用程序一次将多大的报文发送到TCP的缓存中, 而是根据对方给出的窗口和当前网络的拥堵程度来决定一个报文段应该包含多少字节
- MSS: Max Segment Size. 默认 536byte 实际数据
- 报文没有收到ack消息的话将会重传
数据可靠性传输
停止等待协议
即发送一个分组就停止发送, 等待对方确认, 确认后再发送下一个分组
重传机制
- ack报文丢失: 请求报文收到但是回复的ack报文丢失, 也会导致重传
- 请求报文丢失: 直接是请求报文丢失, 那么自然不会ack, 所以会超时重传
滑动窗口协议与累计确认(延时ack)
- 因为停止等待和重传机制非常的效率低下, tcp通过这个协议解决信道效率低,增加吞吐量.
- 上面提到 ack 其实非常浪费时间, 那么如何破除停止等待协议? 使用滑动窗口协议. 允许发送方在停止并等待确认前发送多个数据分组. 由按序到达的最后一个分组发送确认. 发送确认即表明这个窗口全部收到, 那么窗口将会滑动到后面.
- 12345全部收到, 窗口将会滑动到6;
- 如果12345只收到了1245, 发送的确认信息告诉对方3没有收到, 那么窗口将会滑动到3
- 滑动窗口大小通过tcp三次握手和对端协商, 且受网络状况影响.
HTTPS协议
HTTP天生”明文”, 整个传输过程透明. HTTPS就是为了安全而诞生的
HTTPS其实就是HTTP的基础上增加了一个安全层. 在HTTP和TCP之间使用SSL/TLS构成安全层.
- 原本HTTP直接与TCP交互
- 使用安全层后, HTTP层与安全层交互, 安全层再与TCP交互
SSL/TLS
SSL: 安全套接层(Secure Sockets Layer)
TLS: 传输层安全(Transport Layer Security). 1999年IETF将SSL改名为TLS. 现已发展到1.3. 版本紧跟密码学研究.
摘要算法
md5, sha1, sha2, sha256
摘要算法能把任意长度的数据”压缩”成固定长度, 并且独一无二.
所以通过将明文的信息的摘要和明文一起加密进行传输, 数据接收方解密, 重新对数据进行摘要, 再比对就可以发现数据有没有被篡改. 保障了数据的完整性.
加密算法
- 对称密钥加密算法
- 编解码使用相同密钥
- AES, RC4, ChaCha20
- 经典实现: xor异或
- 将原文与密钥异或得到密文
- 非对称密钥加密算法
- 一个叫公钥, 一个叫私钥. 公钥公开, 私钥保密. 发送方用公钥加密数据传输, 密文只能由私钥持有者(接收方)才可能解密.
- 需要大量数学运算, 比较慢.
TLS里使用的混合加密方式, 即把对称加密和非对称加密结合起来, 两者互相取长补短.
- 通信开始使用非对称算法解决密钥交换的问题. 对方服务器发送公钥(公钥数字证书).
- 在连接之初client发送有一个加密套件列表进行
- 服务器在client支持的加密套件中选择一个加密套件返回公钥数字证书
- 密钥交换之后, 使用对称加密来传输数据
这里有一个重点, 就是, 我是通过这种方式来保证传输安全了, 那万一对面根里其实就烂了(server就是fake)呢?
这样我们需要一个方法来确保公钥是正确的server发送的. 这里就出现了一个机构也就是CA机构.
所以其实上面发送的公钥是一个公钥数字证书, 是由CA机构颁发的. 证书包含CA信息, 公钥用户信息, 公钥, 权威机构的签名, 有效期等等.
那肯定我就又有疑问了. 那CA也烂了咋办?
所以其实CA证书是一个证书链, 逐层向上验证, 一直到最后有一个根证书来提供最后的保障. 这个不是走互联网的, 这个是操作系统写入的. 所以也就是说我们确保了最最根部的CA证书是正确的, 剩下的逐层验证即可.
到此为止也算是把http和tcp还有https过了一遍了, 深度肯定还不够, 譬如tcp的拥塞控制还没有写. 这个我觉得需要另开一个篇章去写, 就不放到http协议这里了.
拥塞控制可以参考这篇文章: https://zhuanlan.zhihu.com/p/37379780
OK! 努力年薪百万.