zoukankan      html  css  js  c++  java
  • 从一个HTTP请求来读懂HTTP、TCP协议

    from:https://www.toutiao.com/i6885366707725009419/

    从一个HTTP请求来看网络分层原理

    两台主机间会通过非常多网络设备,不管哪个网络设备都会发生数据丢失,如果发生数据丢失的话,会发生数据重传,会出现数据重复(之前丢失的包并不是丢失而是产生了延时)。数据传输的介质也可能多样,如内网里通过网线进行传输,连接到公网的话会通过光纤进行连接,所以要实现不同介质间信号的转换,还有从光纤到路由器无线脉冲转换,距离远的话还有信号衰减问题。所以在网络传输过程中有非常多的问题需要解决,把问题分组分层,不同层次间解决不同问题,不同层次间定义标准化接口让它们间可以进行数据的通信。

    复杂的网络

    clip_image001

    为了简化网络的复杂度,网络通信的不同方面被分解为多层次结构,每一层只与紧挨着的上层或者下层进行交互,将网络分层,这样就可以修改,甚至替换某一层的软件,只要层与层之间的接口保持不变,就不会影响到其他层。

    · OSI( Open System Interconnection Reference Model): 开放系统互联参考模型

    · TCP/IP 协议族

    OSI七层理论体系结构

    clip_image002

    1. 物理层:解决两台主机的通信问题—A往B发送比特流(0101),B能接收到这些比特流。定义了物理设备的标准如网线的类型,光纤的接口类型以及传输介质的传输速率等。

    2. 数据链路层:由于物理层上的传输的比特流可能会出现错传、误传等,所以数据链路层定义了如何格式化数据即将比特流封装成,提供了错误检测。

    3. 网络层:随着节点的增加,点对点通信是需要经过多个节点的,如何找到目标节点,如何找到最优路径变成为了首要需求。所以出现了网络层,主要目的是将网络地址翻译成对应的物理地址,分组传输、路由选择,本层的传输单位是数据报(分组),本层需要注意的TCP/IP协议中的TCP协议。

    4. 传输层:随着网络需要的进一步扩大,通信过程中需要传输大量的数据,网络可能会发生中断,为了保证传输大量文件时的准确性,需要对发送的数据进行切分,切分成一个个的segment进行发送,考虑如何在接受方拼接切分的segment组成完整的数据,以及发现丢失segment时该如何处理,需要注意的协议TCP、UDP。

    5. 会话层:不同机器上的用户之间建立以及管理会话。用于保证应用程序自动收发包和寻址。

    6. 表示层:信息的语义语法,加密解密,转换翻译,压缩解压缩。

    7. 应用层:规定双方必须使用固定长度的消息头,且消息头必须记录消息长度等信息。需要注意的是TCP/IP协议中的HTTP协议。

    clip_image003

    TCP/IP四层模型

    是OSI的一种实现,包括应用层、运输层、网际层和网络接口层。

    clip_image004

    一个HTTP请求的分层解析流程

    clip_image005

    如上图右边一个服务器部署了一个静态页面,通过nginx部署在公网上,浏览器通过域名对它进行访问,浏览器输入域名点回车后是怎么工作的呢?

    http://www.dumain.com

    服务端只认ip地址,浏览器将域名解析出来,看下浏览器里有没有域名对应DNS的缓存,有的话直接拿到服务端的ip地址,没有的话去本地的host文件看有没有配置,没有配置的话才会发起一个DNS请求用来获取服务器ip地址。

    DNS也是台服务器也有自己的ip地址,这时候应用层会构造一个DNS请求报文,应用层会去调用传输层的接口一个socket的API,DNS默认使用UDP实现数据传输,即应用层调用传输层的API,传输层会在DNS请求报文基础上加一个UDP的请求头,传输层将数据交给网络层,网络层同样在UDP请求报文基础上加IP的请求头,网络层会将IP请求报文交给数据链路层,数据链路层会将自己的mac头加上去并把对应的请求报文交给下一个机器的mac地址也会加上去,下一个机器的mac地址通过网络层ARP协议找到,ARP会发送一些请求看下你对应的ip地址的mac地址是多少,最后通过物理层物理介质传出去,通常传到路由器上.

    路由器是三层设备(从下向上)从物理层开始连接,物理层交给数据链路层,数据链路层看下地址是不是给我的,是给我的进行解析,不是给我的就丢弃,报文再传给上面一层网络层,网络层把数据传到下一个路由器的地址是多少,会通过运营商的网络接口传到运营商的路由器上,运营商有自己的DNS服务器,如果配置的是运营商自己的DNS服务器的话会直接在这个DNS服务器里找自己对应的域名拿到对应的ip地址,也就是刚请求DNS报文地址,然后原路返回解析直到应用层拿到刚域名对应的ip地址,这样就可以进行HTTP请求报文的发送,再调用传输层协议是TCP参数,同样每到一层加头。

    HTTP

    什么是HTTP?

    超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。

    HTTP特点

    1. 无状态:协议对客户端没有状态存储,对事物处理没有“记忆”能力,比如访问一个网站需要反复进行登录操作。

    2. 无连接:HTTP/1.1之前,由于无状态特点,每次请求需要通过TCP三次握手四次挥手,和服务器重新建立连接。比如某个客户机在短时间多次请求同一个资源,服务器并不能区别是否已经响应过用户的请求,所以每次需要重新响应请求,需要耗费不必要的时间和流量。

    3. 基于请求和响应:基本的特性,由客户端发起请求,服务端响应。

    4. 简单快速、灵活。

    5. 通信使用明文、请求和响应不会对通信方进行确认、无法保护数据的完整性。

    HTTP协议版本已经演化到3.0版本,关于协议版本可以查看 快速掌握HTTP1.0 1.1 2.0 3.0的特点及其区别

    HTTP报文格式

    HTTP 协议的请求报文和响应报文的结构基本相同,由三大部分组成:

    · 起始行(start line):描述请求或响应的基本信息

    · 头部字段集合(header):使用 key-value 形式更详细地说明报文

    · 消息正文(entity):实际传输的数据,它不一定是纯文本,可以是图片、视频等二进制数据

    其中起始行和头部的字段并成为 请求头 或者 响应头,统称为 Header;消息正文也叫实体,称为 body。HTTP 协议规定每次发送的报文必须要有 Header,但是可以没有 body,也就是说头信息是必须的,实体信息可以没有。而且在 header 和 body 之间必须要有一个空行(CRLF)。

    clip_image006

    请求行报文格式

    clip_image007

    · 请求方法:如 GET/HEAD/PUT/POST,表示对资源的操作;

    · 请求目标:通常是一个 URI,标记了请求方法要操作的资源;

    · 版本号:表示报文使用的 HTTP 协议版本。

    响应报文格式

    clip_image008

    · 版本号:表示报文使用的 HTTP 协议版本;

    · 状态码:一个三位数,用代码的形式表示处理的结果,比如 200 是成功,500 是服务器错误;

    · 原因:作为数字状态码补充,是更详细的解释文字,帮助人理解原因。

    请求及响应报文格式对比

    clip_image009

    HTTP 头字段

    头部字段是 key-value 的形式,key 和 value 之间用“:”分隔,最后用 CRLF 换行表示字

    段结束。比如前后分离时经常遇到的要与后端协商传输数据的类型“Content-type: application/json”,这里 key 就是“Content-type”,value 就 是“application/json”。HTTP 头字段非常灵活,不仅可以使用标准里的 Host、 Connection 等已有头,也可以任意添加自定义头,这就给 HTTP 协议带来了无限的扩展可能。

    头字段注意事项

    · 字段名不区分大小写,字段名里不允许出现空格,可以使用连字符“-”,但不

    · 能使用下划线“_”(有的服务器不会解析带“_”的头字段)。字段名后面必须紧接 着“:”,不能有空格,而“:”后的字段值前可以有多个空格;

    · 字段的顺序是没有意义的,可以任意排列不影响语义;

    · 字段原则上不能重复,除非这个字段本身的语义允许,例如 Set-Cookie。

    HTTP 协议中有非常多的头字段,但基本上可以分为四大类:通用标头、实体标头、请求标头、响应标头。

    HTTP 头字段更多内容请查看《深入掌握HTTP四种标头基本概念

    TCP 协议

    TCP(Transmission Control Protocol),传输控制协议:面向连接的,可靠的,基于字节流的传输层通信协议。它能帮助你确定计算机连接到 Internet 以及它们之间的数据传输。通过三次握手来建立 TCP 连接,三次握手就是用来启动和确认 TCP 连接的过程。一旦连接建立后,就可以发送数据了,当数据传输完成后,会通过关闭虚拟电路来断开连接。

    TCP特点

    · 基于连接的:数据传输之前需要建立连接
    全双工的:双向传输

    · 字节流:不限制数据大小,打包成报文段,保证有序接收,重复报文自动丢弃

    · 流量缓冲:解决双方处理能力的不匹配

    · 可靠的传输服务:保证可达,丢包时通过重发机制实现可靠性

    · 拥塞控制:防止网络出现恶性拥塞

    TCP报文格式

    clip_image010

    · 16位源端口/16位目的端口:负责实现应用程序之间的数据传输

    · 32位序号/32位确认序号:用于实现tcp在传输层的包序管理——tcp有序交付数据

    · 4位头部长度:以4个字节为单位;4位保存的最大数字是15;因此tcp报头最大长度是15*4=60个字节

    · 6位保留位

    · 6位标志

    · URG——紧急指针标志

    · ACK——确认回复标志

    · PSH——提示立即接受位

    · RST——重置连接位

    · SYN——连接建立请求位

    · FIN——断开连接请求位

    · 16位窗口大小:滑动窗口机制–>流量控制–>告诉对端所能发送的最大数据量

    · 校验和:二进制反码求和–>校验数据一致性

    · 紧急指针:指明哪些数据是紧急数据

    · 选项数据:三次握手时,协商MSS大小的数据

    TCP连接:四元组[ 源地址, 源端口, 目的地址, 目的端口 ]

    TCP三次握手

    · 同步通信双方初始序列号( ISN, initial sequence number )

    · 协商TCP通信参数(MSS, 窗口信息,指定校验和算法)

    在了解具体流程之前,我们先认识几个概念

    clip_image011

    最初两端的TCP进程都处于CLOSED关闭状态,A主动打开连接,而B被动打开连接。

    A、B关闭状态CLOSED — B收听状态LISTEN — A同步已发送状态SYN-SENT — B同步收到状态SYN-RCVD— A、B连接已建立状态ESTABLISHED

    B的TCP服务器进程先创建传输控制块TCB,准备接受客户进程的连接请求。然后服务器进程就处于LISTEN(收听)状态,等待客户的连接请求。若有,则作出响应。

    · SYN:它的全称是 Synchronize Sequence Numbers ,同步序列编号。是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立 TCP 连接时,首先会发送的一个信号。客户端在发送 SYN 消息时,就会在自己的段内生成一个随机值 X

    · SYN-ACK:服务器收到 SYN 后,应答客户端连接,发送一个 SYN-ACK作为答复。确认号设置为比接收到的序列号多一个,即 X + 1,服务器为数据包选择的序列号是另一个随机数 Y

    · ACK: Ackowledge character ,确认字符,表示发来的数据已确认接收无误。最后客户端将 ACK 发送给服务器。序列号被设置为所接收的确认值即 Y+ 1

    clip_image012

    下面通过一个案例看三次握手是怎么进行的

    · 在Nginx服务器部署一个静态页面(我的端口为:8000)

    clip_image013

    · tcpdump指定网卡进行监听抓取报文

    tcpdump -i en0 -S -c 3 port 8000

    · 在客户端使用nc网络工具发送一个请求

    nc 192.168.109.200 8000

    · 三次握手监听结果如下:

    clip_image014

    · 内核在三次握手做的一些事情,如下:

    clip_image015

    · 连接状态查看

    netstat -tpn # t:TCP连接装,p:进程显示 ,n:数字形式

    # 每秒查看一次

    netstat -tpn -c 1

    clip_image016

    TCP四次挥手

    clip_image017

    · A: 发送FIN数据包,代表A不再发送数据

    · B: 收到请求,开始应答 ,避免了A重新发送FIN重试(应答机制)

    · B: 处理完数据之后关闭,关闭连接,及发送FIN请求

    · A: 收到请求后发送ACK应答,B服务可以释放连接

    等待 2MSL后释放连接

    1. 防止报文丢失,导致B重复发送FIN

    2. 防止滞留在网络中的报文,对新建立的连接造成数据扰乱

    字节流的协议

    TCP把应用交付的数据仅仅看成是一连串的无结构的字节流,TCP并不 知道字节流的含义,TCP并不关心应用程序一次将多大的报文发送到 TCP的缓存中,而是根据对方给出的窗口值和当前网络拥堵的程度来决 定一个报文段应该包含多少个字节。

    MSS: Max Segment Size, 默认 536byte 实际数据

    clip_image018

    在网络传输过程中可能会出现以下的一些情况:

    · 客户端一段时间没有收到 ack 消息则重传

    · 如果缓冲区满了则可能丢包或延时都需要重传

    · 根据报文 sequeence number 字段重排序,还需要丢弃重复包。

    数据传输的可靠性

    停止等待协议如下:

    clip_image019

    停止等待协议,效率比较低

    重传机制如下:

    · ack 报文丢失

    clip_image020

    · 请求报文丢失

    clip_image021

    滑动窗口协议与累计确认(延时ack)

    如上效率低,所以tcp提出了新的协议-滑动窗口协议与累计确认(延时ack)。

    滑动窗口大小同通过tcp三次握手和对端协商,且受网络状况影响。

    上面是一个一个报文,实际可发一批报文,服务器并不是挨个去确认,上面回一个ack浪费资源,单独响应一个报文时,tcp本身一个报文至少20个字节再加上ip头报文20字节,所以一个ack至少40字节。

    所以延时ack的发送,如下图确认最后一个报文如5就可以,但这样也有一个问题如3的报文丢了,这时只能确认1和2连续报文,从3以后的报文全要重传,已确认的报文在缓冲区丢弃掉。

    clip_image022

  • 相关阅读:
    1063. Set Similarity
    A1047. Student List for Course
    A1039. Course List for Student
    最大公约数、素数、分数运算、超长整数计算总结
    A1024. Palindromic Number
    A1023. Have Fun with Numbers
    A1059. Prime Factors
    A1096. Consecutive Factors
    A1078. Hashing
    A1015. Reversible Primes
  • 原文地址:https://www.cnblogs.com/94cool/p/13948489.html
Copyright © 2011-2022 走看看