0


TCP/IP协议

本篇将详细介绍TCP/IP协议中的每一层里面的核心内容

1. 应用层

应用层是和应用程序密切相关的,不同的应用程序,里面可能会涉及到不同的应用层协议。

在写代码时有相当一部分的工作量,就是在自定义应用层协议

自定义应用层协议从两方面考虑:【都是根据需求】

a)考虑要在客户端和服务器之间传输哪些信息

b)考虑信息/数据按照啥格式组织

例子:点外卖

典型场景:展示商家列表

针对这个场景,如何自定义协议

1. 明确传输的信息,请求里有啥,响应里有啥

请求:用户的位置,用户的喜好

响应:商家列表,要包含多个商家信息,每个商家包含:商家的名称、图片、评分、距离

2. 明确数据的格式

网络上传输的数据本质都是bit流(一堆二进制位),也可以把这些数据视为“字符串”

比如:

请求:经度,维度;偏好炒菜,小炒泡馍,面食;

(请求中有两部分,位置信息和偏好信息。中间使用 ; 来分割

位置信息和偏好信息内部的各个部分使用 , 来分割)

响应:XX小炒泡馍,图片,5星,800m;

** XX炒菜管,图片,5星,1km;**

(响应中包含多个商家信息,每个商家占一行,每行里面多个属性之间使用 , 来分割)

这个格式,在自己写代码时可以根据自己的喜好来写,并不是一定要这样写

但是写代码太灵活了也不好,所以就有一些比较特定的数据传输格式,基于这些常用的格式来传输数据,就可以更通用,也更方便

1.HTTP应用层中最重要的,也最常用的协议

2.XML比较典型的数据组织格式,不过现在不常用了

格式非常有特点,是通过“标签”的形式来组织 键值对 数据的。

例如:商家列表功能

请求:

<request>
        <postion>
                <jingdu>aaa</jingdu>
                <weidu>bbb</weidu>
        </postion>

        <preferences>
                    <preference>炒菜</preference>
                    <preference>小炒泡馍</preference>
        </preferences>
</request>

XML缺点:a.丑 b.数据多了编写复杂

c.这些数据要通过网络编程,消耗网络带宽的

由于这里包含了大量的标签,就导致网络带宽占用的的更高了

3. JSON当前最流行的一种数据组织格式。相当于XML的替代品

{
   position:{
      jingdu:aaa,
      weidu:bbb
   },
   preference:{
      '炒菜','小炒泡馍','面食'
   }
}

JSON首先是一个{},{}里面包含多组键值对,键值对之间使用,来分割

键和值之间,使用:来分隔

键只能是字符串类型,

值可以是字符串,数字,数组,json

JSON优点:a)可读性非常好 b)看起来美观整洁 c)扩展性强

JSON缺点:引入额外的字符串,传输数据量变大了,消耗更多的带宽

  1. 前面的XML和JSON都是属于占用带宽较高,效率较低的格式,但也有些格式,能够更高效的组织数据,其中最典型的叫做 protobuffer(谷歌搞的)

protobuffer既是一个数据格式,同时也是一个库,来操作这种格式的数据

这是一个二进制的格式,这种格式下,组织出来的数据占用空间要比JSON和XML传输效率有明显提升。但二进制不方便阅读,所以这个格式适用于运行效率比较高的场景来使用


2. 传输层

传输层是负责端到端之间的传输,重点关注的是起点和终点

核心的协议有两个:

UDP:无连接,不可靠传输,面向数据报,全双工

TCP:有连接:可靠传输,面向字节流,全双工

2.1 UDP协议

      课本上是这样画的,但实际应该是这样的

如果需要使用UDP传输一个比较大的数据,就需要考虑进行拆包,把一个大的数据报,拆成多个小的。但是在应用层这里对数据进行拆包,拆为多个UDP数据报,分别进行传输,开发起来会比较复杂,测试起来也比较复杂,风险较高

所以直接使用TCP,TCP是字节流的,没有对包的长度做出限制

UDP的校验和使用一个比较常见的CRC算法(循环冗余校验)

把UDP报文中的每个字节,都进行累加,加和 也放到 两个字节 的数字中,加的过程中如果溢出了,就溢出,最终得到的就是校验和


2.2 TCP协议(*三次握手四次挥手重点!!!)

TCP的基本特性

面向字节流,有连接,全双工,代码中都是有所体现的

但是可靠传输(TCP中最核心的特性!!!),在代码中体现不出来

可靠传输指的是,数据传输过去之后,发送方知道我发成功了还是没成功


2.2.1 确认应答机制

(1)确认应答机制:我发送一条数据,你给我来个应答(应答报文,也称为ack报文),通过这个应答,我就知道我这个数据是不是发出去了

确认应答机制,就是TCP保证可靠性的最核心机制

(“三次握手四次挥手”只是一定程度上保证可靠性,但这不是核心的!!!)

网络上可能会有一种情况,“后发先至”(后发的请求,可能会先到达对方这里)

网络上通信传输的路径,是复杂的,两点之间,两个报文走不同的路线

但可以在确认应答这个机制中,引入序号来保证不出现歧义(给请求和响应加上编号)


2.2.2 超时重传

(2)超时重传

确认应答描述的是,数据报顺利到达对方,对方给了个响应

但是传输过程中,可能会丢包,如果丢包怎么办

a. 丢包的原因:网络环境极为复杂,我们能上网,是因为接入了运营商的网络。运行商这边就有很多的路由器/交换机,共同组建出一个非常庞大复杂的网络。某个交换机上,不单单是传输我的数据报,也在传输别人的数据报,某个时刻,极多的数据报都要经过这个交换机。交换机的转发能力不是无上限的,很多数据报走到这里,导致达到交换机的转发上限,无法快捷的完成转发了,就可能会导致有一部分数据报就超时了。

b. 如果数据掉包了,此时就要考虑通过“超时重传”来进行了

接收方因为丢失ACK就会导致收到重复的消息,TCP就会针对相同的消息进行去重(根据序号来去重就可以)

c. 超时时间是如何确定的

一般系统里面会有一个配置项,描述超时的时间阀值

比如:第一次出现丢包,发送方就会在达到超时时间阀值之后,进行重传。如果重传的数据仍然无响应,还会继续超时重传。第二次的超时时间一般要比第一次更长。

超时时间并非均等的,而是逐渐变大的(没有具体的数字)

这样重传,重试几次之后,仍然无法传输,就会尝试重置TCP连接(断开重连)

如果还是连不上,此时就直接释放连接(彻底放弃)

2.2.3 连接管理

(3)连接管理:描述的就是TCP建立连接和断开连接的过程

TCP连接只是“逻辑上的”“虚拟上的连接”

a. 建立连接(双方建立一个相互认同的关系,三次握手)

三次握手(本来是四次,但是中间两次,可以合并在一起)

客户端申请一下,尝试建立连接(三次握手只能是客户端先握)

通信双方,各自向对方申请,尝试和对方建立连接,然后再各自给对方回应

建立连接的过程其实是四次的数据交互

从TCP角度看建立连接(面试考!!!)

** 为啥要建立连接,建立连接的意义是什么**

1)检查一下当前的网络情况是否是通畅的

(三次握手建立连接并不传输任何业务数据)

2)三次握手同时也是在检查通信双方的 发送能力 和 接收能力都是正常的

3)三次握手过程中,也在协商一些重要的参数

两个重点的TCP状态:

LISTEN:服务器启动之后,绑定端口之后(new ServerSocket 完成)

表示 手机开机,信号良好,就可以让别给他打电话了

ESTABLISHED(E stable stablished):连接建立好了之后的稳定状态

表示电话接通,可以说话了

b. 断开连接(双方取消相互认同的关系,四次挥手)

通信双方,各自向对方申请断开连接,再各自给对方回应(客户端或服务器不管谁先挥手都可以)

四次挥手 不一定能合并为三步,这是因为一个是操作系统内核负责,一个是应用程序负责,所以不能合并,但TCP里还有

两个重点的TCP状态

CLOSE_WAIT 等待代码中调用close操作

如果服务器上出现大量的CLOSE_WAIT状态的连接,说明代码bug!

说明close没有被及时调用到

TIME_WAIT 主动发起关闭的一份,会进入到TIME_WAIT

A处理完最后一个ACK之后,不能立即释放连接,而需要保持一定的时间

这个是为了万一最后的ACK丢了,还有机会进行重传


2.2.4 滑动窗口

(4)滑动窗口(提高TCP传输效率的有效机制)

TCP能够保证可靠传输,但是失去了效率

所以TCP希望能够在保证可靠性的前提下,尽可能的提高传输效率(尽管TCP再怎么提升效率,效率也不可能超过UDP),这就引用了滑动窗口来提高传输效率

a. 没引入滑动窗口前,效率非常低,一问一答

** b. 引入滑动窗口后,批量发送消息**

更详细的步骤是这样

前面都是正常情况下。但如果出现丢包 / 乱序 怎么办

丢包两种情况:1.传的数据丢了 2.响应的ACK丢了

  1. 数据包已经抵达,ACK被丢了

  1. 数据包直接丢了

上面的,只是把丢的数据包进行了重传,没丢的包,并没有重传,(没有做任何重复多余的工作),所以这样的重传,效率是比较高的

这也叫做 “快速重传” (搭配滑动窗口机制的超时重传)

虽然,这里说了快速重传。但并不是说 超时重传 就没作用了

如果传输的数据很多,批量传输,那么自然是遵守 快速重传 的方式

如果传输的数据很少,此时仍然按照 超时重传 的方式进行(比如传输中最后一个丢了,那么这就可以用超时传输了)

TCP滑动窗口,窗口大小越大,确实发送速度会更快,但是窗口不能无限大

发送的速度快了,但是接收方,处理不过来啊,这就会导致接收方就丢弃一部分数据

TCP是要保证可靠性(最重要的)的,TCP还得重传这些数据,(这就是让本来不富裕的接收方,更qiong了)

这就需要再有其他的机制,来对发送发的发送速度,做出限制


2.2.5 流量控制

(5)流量控制:在滑动窗口的基础上,对发送速率做出限制的机制

就是限制发送方的窗口大小不要太大

a. 那么窗口大小,应该多大,怎么来规定这个大小?

这就要问一下接收方,看接收方,认为发多快合适

接收方对于发送方的反制,接收方根据自己的接收能力,来反向影响发送方接下来的发送速率

b. 那么接收方的接收速率,如何进行量化?

接收方使用接收缓冲区的剩余空间大小,来作为发送方发送速率(窗口大小)的参考数值

16位窗口大小+选项(扩展因子)

c. 缓冲区中空闲空间了,如何告诉给A?

** 流量控制,是通过接收方的处理能力,来衡量发送方的速率的**


2.2.6 拥塞控制

(6)拥塞控制:将中间这些结点看为“整体”,进行动态平衡的调整

前面只是考虑了接收方的处理速率,但处理方难道就可以随便的发送了吗?

显然也不是,还得考虑中间这些转发节点的情况

拥塞控制,从小的开始,逐渐变大,如果丢包再变小,反复动态调整【宏观策略】

流量控制,在控制发送方的窗口大小

拥塞控制,也是在控制发送方的窗口大小

有分歧的时候,听最小的

** 那么TCP实现拥塞控制具体方式是什么? 慢启动机制**

上面的这个过程,是TCP传统的拥塞控制的实现(以前是这样搞的)

而后来的TCP也在进行演化,拥塞控制也做出了一些改进

其中的改进就是回归不再回归到初始值了,而是回归到一个中间的值


2.2.7 延迟应答

(7)延迟应答:提高传输效率的机制,又是基于流量控制,来引入的提高效率的机制

延时应答核心思路,只要把ACK返回稍微迟一点,就这个短时间段里面,就可以让应用程序有更多的操作空间,来把缓冲区数据进行消耗,而这个消耗肯定会导致接下来的返回的窗口,比立即返回的窗口就要略大(窗口大了,发送数据就快了,整体传输效率就快了)


2.2.8 捎带应答

(8) 捎带应答,基于延时应答的基础上引入的

捎带应答,不是100%发生的


2.2.9 面向字节流

(9)面向字节流:粘包问题

面向字节流中,存在一个典型的问题,叫做“粘包问题”

粘包问题:TCP自身对于应用层数据报是无法做区分的

UDP面向数据报,是不存这个问题的

一个UDP数据报,就是对应一个应用层报文

当前要想解决粘包问题,就是要在应用层协议这里进行区分

只要定义应用层数据协议的时候,明确包和包之间的“边界”就可以了

典型的方法有两种:

(1)通过分隔符,比如约定使用 ; 作为包的结束标记

(2)通过指定包的长度,比如在数据包的开头位置声明长度

2.2.10 TCP中的异常处理

** (10)TCP中的异常处理**

a) 程序崩溃了

进程异常退出

操作系统就会回收进程的资源,包括释放文件描述符表,这样的释放操作,就相当于调用了socket的close,执行close就会触发FIN报文,进一步的开始四次挥手

这种情况和普通的四次挥手实际没啥区别

b)正常关机(通过 开始菜单 这种方式来关闭主机)

关机的时候,系统会先强制结束所有的用户进程,和上述的那个进程奔溃类似

系统内核,会进行文件描述符的释放操作,进一步的进行四次挥手

c)主机掉电

非常突然,猝不及防

1)掉电的是接收方,发送方是不知道对面挂了,继续发数据

此时发的数据,没有ack了,发送方触发超时重传

重传几次之后,仍然无应答,尝试重置连接(复位报文段,RST),也会失败,只能放弃连接

2)掉电的是发送方,此时接收方就等着

接收方也不是就一直等待着,而是等了一会之后,就会发送一个“心跳包”,心跳包是周期性触发的,只是一个简单的不携带任何业务数据的包,存在的意义就是确认一下对方是否还在

d)网线断开

情况同主机掉电

只不过通信双方的主机都是好着的,这两端各自按照上述讲的两种情况分别进行


2.3 TCP和UDP之间的对比

TCP在 有可靠性要求的场景 应用非常广泛

UDP对于可靠性要求不高,但对于传输效率要求很高的情况使用非常广泛

比如机房内部的内网传输,不容易丢包,对传输效率要求比较高,就可以使用UDP

传输层也不是只有UDP TCP 两个协议,还有其他的协议


3. 网络层

网络层做的工作,就是在两点之间,规划出一个合理的路径,同时也需要对主机所在的位置进行定义

这里网络层做的工作:1.地址管理 2.路由选择

认识一下IP协议的报文格式

3.1 IP地址不够用的问题解决方案

1.动态分配IP地址

设备上网的时候才分配给IP地址,不上网的时候,就把IP地址回收,给别人用

**2.NAT机制 **

不再强制要求,每个主机都要有独立的IP,把IP地址分为两大类

a)外网IP / 公网IP

b)内网IP / 私网IP / 局域网IP

只要求外网IP 不能重复,内网IP则在不同的局域网中是允许重复的

常见的内网IP 10.* 172.16.* - 172.31.* 192.168.*

当前网络现状的就是 动态分配 + NAT

3.IPV6 能够彻底解决IP地址不够用的问题

IPv4 4字节,32位来表示IP地址 (42亿9千万)

IPv6 16字节,128位来表示IP地址 (42亿42亿42亿 *42亿)

所以IPv6 远远超过 IPv4 的可表示IP地址个数

(给地球的每一粒沙子都分配一个IP地址,也是足够的)

但是IPv6总体来说还没有大规模普及,当前网络现状还是 NAT+动态分配,这是因为IPv6和IPv4不兼容的问题,要想升级就要花钱更换设备


3.2 地址管理

IP地址具体的规则

IP地址分为两部分,网络号和主机号

网络号:表示网段,在两个相邻的局域网中,要求网络号是不同的(同一个路由器连接的局域网)

也就是在同一个路由器中,WAN和LAN口得有不同的网络号

主机号:表示主机,同一个局域网中,主机之间的网络号是相同的,主机号必须不同

子网掩码:划分出从哪里到哪里是一个网络号

子网掩码是32位的,左半边都是1,右半边都是0(不会是10混着)

左半边有多少个1,就表示IP地址左侧的多少位是网络号

(把子网掩码和IP地址进行按位与运算,得到的结果就是网络号)

** 还有一种网络号和主机号的划分方式(这种方式已经特别老了,现在不用了)**

这种分配方式比较死板,而且比较浪费(比如B类中,我这里只有20个设备,把这个网络号分配给我后,主机号是6w个,实际我只用了20个)

特殊的IP地址

(1)如果一个IP地址,主机号为0,此时这个IP就表示网络号 192.168.0.0,代表当前局域网

(2)如果一个IP地址,主机号为1,此时这个IP往往表示这个局域网的“网关”,

192.168.0.1代表局域网的网关(通常就是路由器的IP,可以手动修改)

网关:网关的角色一般就是路由器,看守当前局域网和其他局域网之间的出入口

(3)如果一个IP地址,主机号为全1,此时这个IP表示广播IP

(4)127.开头,都是“环回IP” 典型的就是127.0.0.1,实际上,只要是*127开头的都是环回IP


3.3 路由选择

可以比较于,我要去某个地方,但不知道路怎么走,只能一路走一路问

IP数据报中,就包含了目的IP(我要去哪里),网络数据报到达路由器的时候,路由器自身有一个“路由表”数据结构,(路由表就是这个路由器认识的路),一个路由器无法认识到网络的全貌,但是可以认识附近的一部分

如果当前的目的IP路由器认识,就会给出一个明确的路线

如果当前的目的IP路由器不认识,路由器就会把数据报发给一个“更见多识广”的路由器

(在路由表中有一个默认的选项,下一跳)

但也有可能问了一圈后,也没找到目的地怎么走,比如IP地址不存在(或者不可达)。当数据报转发的次数超过TTL就会把数据报抛弃

路由过程不单单是去找一条路,也是需要筛选一条更好的路

最关键的是路由表数据结构是啥样的,以及路由表数据是咋来的


4. 数据链路层

数据链路层最关键的协议就是 以太网

mac设计的时候是6个字节,所以当前mac地址还是够用的,是可以让每个主机都有独立的mac地址,这个地址是网卡出厂的时候就写好了的

由于当前mac只是在数据链路层使用,只要相邻区域内的设备mac地址不重复就好

因此在网络上,mac地址也可以作为是主机身份标识的一种方式

以太网,就属于传输过程中的基础设施了

把物理层比喻成公路,数据链路层就相当于跑在公路上的卡车

数据链路层里有很多协议,不同的协议,相当于不同型号的卡车,有的卡车载重量大,有的小

以太网就属于载重量比较小的(1500单位是字节)

此时如果要想运输更多的数据,就需要分多个卡车来拉货(IP协议分包保证的)


5.从浏览器这里输入一个URL,到最终展示出页面,这里大概会发生哪些事情(面试题)

这个题有很多角度都可以回答,如果从后端开发来看的话


标签: tcp/ip 网络 java

本文转载自: https://blog.csdn.net/m0_58761900/article/details/127364244
版权归原作者 快到锅里来呀 所有, 如有侵权,请联系我们删除。

“TCP/IP协议”的评论:

还没有评论