作者公众号:org_yijiaoqian
两台主机间会通过非常多网络设备,不管哪个网络设备都会发生数据丢失,如果发生数据丢失的话,会发生数据重传,会出现数据重复(之前丢失的包并不是丢失而是产生了延时)。数据传输的介质也可能多样,如内网里通过网线进行传输,连接到公网的话会通过光纤进行连接,所以要实现不同介质间信号的转换,还有从光纤到路由器无线脉冲转换,距离远的话还有信号衰减问题。所以在网络传输过程中有非常多的问题需要解决,把问题分组分层,不同层次间解决不同问题,不同层次间定义标准化接口让它们间可以进行数据的通信。
为了简化网络的复杂度,网络通信的不同方面被分解为多层次结构,每一层只与紧挨着的上层或者下层进行交互,将网络分层,这样就可以修改,甚至替换某一层的软件,只要层与层之间的接口保持不变,就不会影响到其他层。
是OSI的一种实现,包括应用层、运输层、网际层和网络接口层。
如上图右边一个服务器部署了一个静态页面,通过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参数,同样每到一层加头。
超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准。设计HTTP的初衷是为了提供一种发布和接收html页面的方法。
HTTP协议版本已经演化到3.0版本,关于协议版本可以查看 快速掌握HTTP1.0 1.1 2.0 3.0的特点及其区别
HTTP 协议的请求报文和响应报文的结构基本相同,由三大部分组成:
其中起始行和头部的字段并成为 请求头 或者 响应头,统称为 Header;消息正文也叫实体,称为 body。HTTP 协议规定每次发送的报文必须要有 Header,但是可以没有 body,也就是说头信息是必须的,实体信息可以没有。而且在 header 和 body 之间必须要有一个空行(CRLF)。
头部字段是 key-value 的形式,key 和 value 之间用“:”分隔,最后用 CRLF 换行表示字
段结束。比如前后分离时经常遇到的要与后端协商传输数据的类型“Content-type: Application/json”,这里 key 就是“Content-type”,value 就 是“application/json”。HTTP 头字段非常灵活,不仅可以使用标准里的 Host、 Connection 等已有头,也可以任意添加自定义头,这就给 HTTP 协议带来了无限的扩展可能。
头字段注意事项
HTTP 协议中有非常多的头字段,但基本上可以分为四大类:通用标头、实体标头、请求标头、响应标头。
HTTP 头字段更多内容请查看《深入掌握HTTP四种标头基本概念 》
TCP(Transmission Control Protocol),传输控制协议:面向连接的,可靠的,基于字节流的传输层通信协议。它能帮助你确定计算机连接到 Internet 以及它们之间的数据传输。通过三次握手来建立 TCP 连接,三次握手就是用来启动和确认 TCP 连接的过程。一旦连接建立后,就可以发送数据了,当数据传输完成后,会通过关闭虚拟电路来断开连接。
TCP连接:四元组[ 源地址, 源端口, 目的地址, 目的端口 ]
在了解具体流程之前,我们先认识几个概念
最初两端的TCP进程都处于CLOSED关闭状态,A主动打开连接,而B被动打开连接。
A、B关闭状态CLOSED — B收听状态LISTEN — A同步已发送状态SYN-SENT — B同步收到状态SYN-RCVD— A、B连接已建立状态ESTABLISHED
B的TCP服务器进程先创建传输控制块TCB,准备接受客户进程的连接请求。然后服务器进程就处于LISTEN(收听)状态,等待客户的连接请求。若有,则作出响应。
下面通过一个案例看三次握手是怎么进行的
tcpdump -i en0 -S -c 3 port 8000
nc 192.168.109.200 8000
netstat -tpn # t:TCP连接装,p:进程显示 ,n:数字形式
# 每秒查看一次
netstat -tpn -c 1
等待 2MSL后释放连接
TCP把应用交付的数据仅仅看成是一连串的无结构的字节流,TCP并不 知道字节流的含义,TCP并不关心应用程序一次将多大的报文发送到 TCP的缓存中,而是根据对方给出的窗口值和当前网络拥堵的程度来决 定一个报文段应该包含多少个字节。
MSS: Max Segment Size, 默认 536byte 实际数据
在网络传输过程中可能会出现以下的一些情况:
停止等待协议如下:
停止等待协议,效率比较低
重传机制如下:
滑动窗口协议与累计确认(延时ack)
如上效率低,所以tcp提出了新的协议-滑动窗口协议与累计确认(延时ack)。
滑动窗口大小同通过tcp三次握手和对端协商,且受网络状况影响。
上面是一个一个报文,实际可发一批报文,服务器并不是挨个去确认,上面回一个ack浪费资源,单独响应一个报文时,tcp本身一个报文至少20个字节再加上ip头报文20字节,所以一个ack至少40字节。
所以延时ack的发送,如下图确认最后一个报文如5就可以,但这样也有一个问题如3的报文丢了,这时只能确认1和2连续报文,从3以后的报文全要重传,已确认的报文在缓冲区丢弃掉。
文章持续更新,可以公众号搜一搜「 一角钱技术 」第一时间阅读, 本文 GitHub org_hejianhui/JAVAStudy 已经收录,欢迎 Star。