参考链接:https://blog.csdn.net/weixin_42621338/article/details/87354737?utm_source=app
TCP/IP是一套用于网络通信的协议集合或者系统。TCP/IP协议模型就有OSI模型分为7层。但其实一般我们所谈到的都是四层的TCP/IP协议栈。
网络接口层:主要是指一些物理层层次的接口,比如电缆等
网络层:提供了独立于硬件的逻辑寻址,实现物理地址和逻辑地址的转换。网络层协议包括IP协议(网际协议),ICMP协议(互联网控制报文协议),IGMP协议(Internet组协议管理)
传输层:为网络提供了流量控制,错误控制和确认服务。传输层有两个互不相同的传输协议:TCP(传输控制协议)、UDP(用户数据报协议)
应用层:为文件传输,网络排错和Internet操作提供具体的程序应用
在TCP/IP协议中数据由上至下将数据封装成包,然后再由下至上的拆包。那么数据又是怎么打包的呢?
在装包的时候,每一层都会增加一些信息用于传输,这部分信息叫做报头。当上层数据到达本层的时候,会将数据加上报头打包在一起形成新的数据包继续往下一层传递。拆包的时候就是反着来了,就像俄罗斯套娃一样,拆完最外面一层得到需要的报头,向上传递。
应用层作为TCP/IP协议的最上层,其实是我们接触最多的。
由于在传输层的传输协议大致分成了TCP和UDP,所以在应用层对应的协议也就分成了两部分。
Http协议的工作流程
一次Http操作称为一个事务,其整个工作流程如下:
1)地址解析
比如客户端浏览器请求浏览页面:www.baidu.com。其实这是一个默认路径,因为平常默认会省略协议名、端口号,访问主页的时候路径也会省略,所以完整路径写法是http://www.baidu.com:80/index.html。这就是我们常说的URL统一资源定位符,用来定位我们访问资源在服务器上的位置。
从这个URL中可以分解出协议名、主机名、端口号、访问对象的路径
在这时候需要域名系统DNS协议解析域名,得到主机的ip。
2)封装http请求数据包
将以上部分(我们想要访问的服务器页面资源)结合自己的本机信息生成一个请求数据报文,封装成一个HTTP请求数据包。至于http的请求数据报文什么样,点击这个。
DNS协议工作流程
1)通过域名访问网页
2)计算机会先将域名发送到一个解析域名的服务器上
3)找到服务器ip地址就可以访问了
http封装请求数据包以后传给传输层,tcp协议部分开始运作。这里将数据包和TCP报头生成TCP报文,打包成新的数据包。
TCP报文结构(点击查看详情):
为了完成三次挥手四次握手,这里需要知道序列号seq、确认应答序号ack(小写字母)、控制位:
序列号seq:
因为在TCP是面向字节流的,他会将报文都分成一个个字节,给每个字节进行序号编写,比如一个报文有900个字节组成,那么就会编成1-900个序号,然后分几部分来进行传输,
比如第一次传,序列号就是1,传了50个字节, 那么第二次传,序列号就为51,所以序列号就是传输的数据的第一个字节相对所有的字节的位置。
确认应答ack:
如刚说的例子,第一次传了50个字节给对方,对方也会回应你,其中带有确认应答,就是告诉你下一次要传第51个字节来了,所以这个确认应答就是告诉对方下一次要传第多少个字节了。也就是说告诉序列号下一次从哪里开始
控制位目前有6个
URG:紧急,当URG为1时,表名紧急指针字段有效,标识该报文是一个紧急报文,传送到目标主机后,不用排队,应该让该报文尽量往下排,让其早点让应用程序给接受。
ACK:确认,当ACK为1时,确认序号才有效。当ACK为0时, 确认序号没用
PSH:推送,当为1时,当遇到此报文时,会减少数据向上交付,本来想应用进程交付数据是要等到一定的缓存大小才发送的,但是遇到它,就不用在等足够多的数据才向上交付,
而是让应用进程早点拿到此报文,这个要和紧急分清楚,紧急是插队,但是提交缓存大小的数据不变,这个推送就要排队,但是遇到他的时候,会减少交付的缓存数据,提前交付。
RST:复位,报文遇到很严重的差错时,比如TCP连接出错等,会将RST置为1,然后释放连接,全部重新来过。
SYN:同步,在进行连接的时候,也就是三次握手时用得到,下面会具体讲到,配合ACK一起使用
FIN:终止,在释放连接时,也就是四次挥手时用的。
在通信之前,会先通过三次握手的机制来确认两端口之间的连接是否可用。而UDP是不需要确认的,直接传
最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。
某个时刻客户端和服务器要进行通信,此时双方都有备好的端口,服务器的端口会处于监听状态,等待客户端的连接。
怎么知道服务器端口号的?
http在访问url中已经拿到!
怎么知道客户端要连接进来,服务器才进入listen状态?
TCP老早就创建了传输控制块TCB,时刻待命准备接受客户端的连接请求,此时服务器就被动地进入了listen状态。
第一次握手:
客户端想要连接,创建传输控制块TCB,状态变为主动打开。发送给服务器不包含数据内容的连接请求报文。该请求报文首部中同步位SYN=1,同时选择一个初始序列号seq=x(携带了x个字节)。然后客户端进入 SYN-SENT (同步已发送)状态,告诉服务器我想和你同步连接。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
第二次握手:
TCP服务器收到连接请求报文,如果同意连接则发送确认报文。为了保证下次客户端发送报文时seq序列号是正确的,需要发送确认号ack=x+1,同时确认号ack要生效必须发送ACK=1,再加上同步位SYN=1,序列号seq=y(携带Y个字节),然后服务器也进 入SYN-RCVD (同步已收到) 状态,完成同步连接。这个报文也是SYN报文,也不能携带数据,但是同样要消耗一个序号。
第三次握手:
客户端收到确认后还要再向服务器发送确认报文。确认报文已经不是请求报文SYN了,不再包含SYN同步位。发送的内容有序列号seq=x+1(和第二次握手的ACK对应),确认号ack=y+1,ACK=1。客户端发送确认报文以后进入ESTABLISHED(已建立)状态,服务器接收到确认报文以后也进入ESTABLISHED状态。此时TCP连接完成建立。
然后就可以发送TCP接收到Http的数据包后生成的新数据包了!
但是貌似看起来两次握手请求就可以完成事,为什么非要三次握手呢?
主要是为了防止已经失效的连接请求报文突然又传到了服务器,从而产生错误。
如果是两次握手,假设一种情景:客户端发送了第一个请求连接报文并未丢失,只是因为网络问题在网络节点中滞留太久了。由于客户端迟迟没有收到确认报文,以为服务器没有收到。于是再发送一条请求连接报文,此时一路畅通完成两次握手建立连接,传输数据,关闭连接。然后那个前一条龟速的请求报文终于走到了服务器,再次和服务器建立连接,这就造成了不必要的资源浪费。
如果是三次握手,就算那一条龟速的请求报文最后到达了服务器,然后服务器也发送了确认连接报文,但是此时客户端已经不会再发出确认报文了,服务器也接受不到确认报文,于是无法建立连接。
数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。
第一次挥手:
客户端从ESTABLISHED状态变为主动关闭状态,客户端发送请求释放连接报文给服务器,FIN=1,seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
第二次挥手:
服务器接收到客户端发来的请求释放报文以后,发送确认报文告诉客户端我收到了你的请求,内容差不多就是seq=v,ack=u+1,ACK=1,此时服务器进入CLOSE-WAIT(关闭等待)状态。
为什么是CLOSE-WAIT状态?可能自己服务器这端还有数据没有发送完,所以这个时候整个TCP的连接就变成了半关闭状态。服务器还能发送数据,客户端也能接收数据,但客户端不能再发送数据了,只能发送确认报文。
客户端接收到服务器传来的确认报文以后,进入 FIN-WAIT-1(终止等待2)状态,等待服务器发送连接释放的报文(在这之前,还需要接受服务器没有发送完的最后的数据)。
第三次挥手:
服务器所有的数据都发送完了,认为可以关闭连接了,于是向客户端发送连接释放报文,内容FIN=1,seq=w,ack=u+1(客户端没发送消息,所以提醒客户端下一次还是从u+1开始发送序列),ACK=1。此时服务器进入了 LAST-ACK(最后确认)状态,等待客户端发送确认报文。
第四次挥手:
客户端接收到了服务器发送的连接释放报文,必须发出确认。确认报文seq=u+1,ack=w+1,ACK=1。此时客户端进入 TIME-WAIT (时间等待)状态,但是没有立马关闭。此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
因为这个确认报文可能丢失。服务器收不到确认报文心想这可能是我没传到或者丢失了啊,于是服务器再传一个FIN,然后客户端再重新发送一个确认报文。然后刷新2∗∗MSL时间。直到这个时间内收不到FIN连接释放报文,客户端撤销TCB进入CLOSE状态。
而服务器,在接收到确认报文的时候就立马变为CLOSE状态了。所以服务器结束TCP连接的时间略早于客户端。
万一确认连接以后客户端故障怎么办?
TCP设有一个保活计时器。显然客户端故障时服务器不会智障般等下去,白白浪费资源。服务器每次收到一次客户端的请求以后都会刷新这个保活计时器,时间通常设置为2小时。若2个小时依旧没有收到客户端的任何数据,服务器会发送一个探测报文段,每隔75分钟发一个,如果连发十个都没有数据反应,那么服务器就知道客户端故障了,关闭连接。
TCP数据包到了这一层,再加上IP报文生成新的IP数据包
前面有提到网络层主要负责物理地址(mac)和逻辑地址(ip)的转换。
ICMP(Internet Control Message Protocol:互联网控制消息协议):主要负责网络层和传输层的数据交换,是为了更有效地转发IP数据报文和提高数据报文交付成功的机会,是介于传输层和网络层之间的协议。
ARP(Address Resolution Protocol:地址解析协议):主要是将IP地址解析成MAC地址的协议。
RARP(Reverse Address Resolution Protocol:逆地址解析协议):正好相反,是将MAC地址解析成IP地址的协议。
IP协议(Internet Protocol:网际协议):是TCP/IP协议族中最为核心的协议。它提供不可靠、无连接的服务,也即依赖其他层的协议进行差错控制。
报文结构格式(了解更多):
再谈谈IP地址 :
TCP/IP协议网络上每个网络适配器都有一个唯一的ip地址
IP 地址是一个 32 位的地址,这个地址通常分成 4 端,每 8 个二进制为一段,但是为了方便阅读,通常会将每段都转换为十进制来显示,比如大家非常熟悉的 192.168.0.1(本地局域网)
IP地址分为两部分,一部分是网络ID,另一部分是主机ID。但是具体哪一部分是网络D,哪一部分是主机ID并没有明确规定。因为有的网络需要主机很少,因此较短;而有些比较长,因此主机ID较长。
绝大部分 IP 地址属于以下几类
A 类地址:IP 地址的前 8 位代表网络 ID ,后 24 位代表主机 ID
B 类地址:IP 地址的前 16 位代表网络 ID ,后 16 位代表主机 ID
C 类地址:IP 地址的前 24 位代表网络 ID ,后 8 位代表主机 ID
从以下的图中就可以很简单区分IP地址属于哪一类了,比如我的ip地址192.168.0.1就是属于C类
注意:
1.十进制第一段大于 223 的属于 D 类和 E 类地址,这两类比较特殊也不常见,这里就不做详解介绍了。
2.每一类都有一些排除地址,这些地址并不属于该类,他们是在一些特殊情况使用地址
3.除了这样的方式来划分网络,我们还可以把每个网络划分为更小的网络块,称之为子网
其实这里还可以分为数据链路层和物理层
这一层主要涉及到一些物理传输,比如以太网,无线局域网,电缆等
IP数据包到了这层就不一样了啊!数据链路会在IP数据报的首尾加上首部和尾部代表数据包的结束,封装成帧。首部和尾部都是8位2进制表示,可以一样也可以不一样。
链路:一条点到点的物理线路段,中间没有任何其他的交换结点,通俗的将,就是一根线,其中不经过任何东西,这样的就是链路,一条链路只是一条通路的一个组成部分
数据链路:除了物理线路外,还必须有通信协议来控制这些数据的传输。若把实现这些协议的硬件和软件加到链路上,就构成了数据链路。 通俗讲,就是经过了一些交换机呀,什么的。
最终到达目的地,所有路段就是数据链路,而数据链路中就包含了多段链路。
适配器:也就是网卡,就是用来实现数据链路上一些协议。
帧:数据链路层上传送的就是帧