现今绝大部分项目中都会用到网络用于数据访问。而在工作中基本用到的都是上层已经封装好的第三方库和一些开源的框架。很多人都只知道怎么使用,对框架底层下网络协议很少真正的去了解。作为一个IT从业者,势必要去了解下网络底层。高楼大厦,起于平川。不积跬步,无以至千里,不积小流,无以成江海。
什么是TCP/IP ?
TCP/IP不是一个协议,而是一个协议族的统称。里面包括IP协议、IMCP协议、TCP协议。
TCP/IP 通常被认为是一个四层协议:
- 链路层。也称数据链路层或网络接口层,包括设备驱动程序和网络接口卡,它们一起处理与电缆物理接口细节。
- 网络层。处理分组在网络中的活动。如分组的选路;网络层的协议包括IP协议、ICMP协议(Internet互联网控制协议)、IGMP协议()Internet组管理协议。
- 传输层。主要为两台主机上的应用程序提供端到端的通信,包括TCP(传输控制协议)和UDP(用户数据报协议)。
- 应用层。处理特定的应用程序细节,有http,ftp,等等我们熟悉的协议。
TCP/IP协议族中不同层次的协议如下:
互联网上的每个接口必须有唯一的IP地址,5类不同的IP地址格式和返回如下:
当应用程序用TCP传送数据时,数据被送入协议栈,然后逐个通过每一层直到被当作一串比特流送入网络,其中每一层对收到的数据都要增加一些首部信息。
链路层
链路层主要有三个目的:
1、为IP模块发送和接受IP数据;
2、为ARP模块发送ARP请求和接受ARP应答;
3、外RARP发送RARP请求和接受RARP应答。
环回接口
环回接口允许运行在同一台主机上的客户程序和服务器程序通过TCP/IP进行通信,IP地址127.0.0.1被分配给这个接口,并命名为localhost。
目的地址的环回地址时,照样还是传输层和网络层的所有过程,只是当IP数据报离开网络层时把它返回给自己,这样做简化了设计,因为环回接口可以看作是网络层下面的一个链路层。网络层把一份数据报传送给环回接口,就像传送给其它链路层一样,只不过环回接口把它返回到IP的输入队列中。
MTU
以太网对数据帧的长度有一个限制,最大值1500.链路层的这个特性称作MTU(最大传输大源)。如果IP层数据报的长度比链路层的MTU还要大,那么IP层就需要进行分片,每一片都要小于MTU。
如果两台主机之间的通信要通过多个网络,那么每个网络的链路层就可能有不同的MTU。两台通信主机路径中最小MTU,被称为路径MTU。两个方向上的选路不一定对称,因此路径MTU在两个方向上不一定是一致的。
IP协议
IP是TCP/IP协议族中最为核心的协议。所有的TCP、UDP、ICMP及IGMP数据都以IP数据报格式传输。
IP提供不可靠、无连接的数据服务。不可靠的是指它不能保证IP数据报能成功地到达目的地;无连接是指IP并不维护任何关于后续数据报的状态信息,每个数据报的处理是相互独立的。
IP数据报格式
IP数据报格式如下图所示,普通的IP首部长为20字节,除非含有选项字段。
总长度字段是指整个IP数据报的长度,该字段长16位,所以IP数据报的最大长度为65535字节。
最后一个字段是任选项,是数据报中的一个可变长的可选信息,如记录路径、时间戳等,这些选项一般很少使用。
IP路由选择
IP路由选择是简单的,对于主机来说,如果目的主机与源主机直接相连或都在一个共享网络上,那么IP数据报就直接送到目的主机上;否则主机就把数据报发往一默认的路由器上,由路由器来转发该数据报。
IP层既可以配置成路由器的功能,也可以配置成主机的功能。IP层在内存中有一个路由表,当收到一份数据报并进行发送时,它都要对该表搜索一次。当数据报来自某个网络接口时,IP首先检查目的IP地址是否为本机的IP地址之一或者IP广播地址。如果是的话,数据报就被送到由IP首部协议字段所指定的协议模块进行处理。如果数据报的目的不是这些地址,如果IP层被设置为路由器的功能,那么就对数据报进行转发,否则数据报被丢弃。
IP路由选择是逐跳进行的,IP并不知道到达任何目的的完整路径,所有IP路由选择只为数据报传输提供下一站路由器的IP地址。IP路由选择主要完成这些功能:
1、搜索路由表,寻找能与目的IP地址完全匹配的表目。
2、搜索路由表,寻找能与目的网络号相匹配的表目。
3、搜索路由表,寻找标为”默认”的表目。
如果上面的步骤都没有成功,数据报就不能被传送
子网寻址
现在所有主机都要求支持子网编址。不是把IP地址看成单纯的一个网络号和一个主机号组成,而是吧主机号再分成一个子网号和一个主机号。
主机通过子网掩码来确定IP地址多少位用于子网号,多少位用于主机号。子网掩码是一个32位的值,值为1的位留给网络号和子网号,为0的位留给主机号。
给定IP地址和子网掩码以后,主机就可以确定IP数据报的目的是:(1)本子网上的主机;(2)本网络中其它子网的主机;(3)其它网络上的主机。
UDP
UDP是一个简单的面向数据报的传输层协议。应用程序必须关心IP数据报的长度,如果它超过了MTU,就要对IP数据报进行分片。
UDP首部
UDP首部的各字段如下图:
端口号表示发送进程和接收进程,TCP端口号由TCP来查看,而UDP端口号由UDP来查看,TCP端口号和UDP端口号是相互独立的。
IP数据报的最大长度时65535字节,这是由IP首部16比特总长度字段所限制的。除去20字节的IP首部和8字节的UDP首部,UDP数据报中用户数据的最长长度为65507字节。
IP分片
IP把MTU与数据报长度进行比较,如果需要则进行分片。分片可以发生在原始发送端主机上,也可以发生在中间路由器上。把一份IP数据报分片以后,只有到达目的地才进行重新组装。重新组装由目的端的IP层来完成,其目的是使分片和重新组装过程对传输层透明。
IP数据报中的标识字段包含一个唯一值,该值在数据报分片时被复制到每个片中。标志字段用其中一个比特来表示”更多的片”,除最后一片外,其它每个组成数据报的片都要报该比特置1。片偏移字段指的是该片偏移原始数据报开始处的位置。
由于IP层本身没有超时重传的机制,即使只丢失一片数据也要重传整个数据报。如果对数据报分片的是中间路由器,而不是起始端系统,那么起始端系统就无法知道数据报是如何被分片的。所以要避免分片。
需要注意的是,任何传输层首部只出现在第1片数据中。
IP路由选择
TCP
TCP提供一种面向连接的、可靠的字节流服务。TCP通过以下方式来提供可靠性:
应用数据被分割成TCP认为最合适发送的数据块。
TCP发送一个段后,它启动一个定时器,如果不能及时收到一个确认,将重发这个报文段。
TCP收到发自TCP连接另一端的数据时,将发送一个确认。
TCP将保持它首部和数据的校验和。
TCP对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。
TCP的接收端会丢弃重复的数据。
TCP还能提供流量控制。
TCP/IP的三次握手,四次分手
前提:A主动打开,B被动打开
1、在建立连接之前,B先创建TCB(传输控制块),准备接受客户进程的连接请求,处于LISTEN(监听)状态
2、A首先创建TCB,然后向B发出连接请求,SYN置1,同时选择初始序号seq=x,进入SYN-SEND(同步已发送)状态
3、B收到连接请求后向A发送确认,SYN置1,ACK置1,同时产生一个确认序号ack=x+1。同时随机选择初始序号seq=y,进入SYN-RCVD(同步收到)状态
4、A收到确认连接请求后,ACK置1,确认号ack=y+1,seq=x+1,进入到ESTABLISHED(已建立连接)状态。向B发出确认连接,最后B也进入到ESTABLISHED(已建立连接)状态。
简单来说,就是
1、建立连接时,客户端发送SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认
2、服务器收到SYN包,必须确认客户的SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态
3、客户端收到服务器的SYN+ACK包,向服务器发送确认报ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手
四次分手的过程(客户端我们用A表示,服务器端用B表示)
由于TCP连接时是全双工的,因此每个方向都必须单独进行关闭。这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的链接。收到一个FIN只是意味着这一方向上没有数据流动,既不会在收到数据,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN,首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
有人可能会问,为什么连接的时候是三次握手,而断开连接的时候需要四次挥手?
这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再 发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。
1、A发送一个FIN,用来关闭A到B的数据传送,A进入FIN_WAIT_1状态。
2、B收到FIN后,发送一个ACK给A,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),B进入CLOSE_WAIT状态。
3、B发送一个FIN,用来关闭B到A的数据传送,B进入LAST_ACK状态。
4、A收到FIN后,A进入TIME_WAIT状态,接着发送一个ACK给B,确认序号为收到序号+1,B进入CLOSED状态,完成四次挥手。
TCP首部
TCP首部的数据格式如下图:
序号用来标识从TCP发送端想TCP接收端发送的数据字节流,它表示在这个报文段中的第一个数据字节,TCP用需要对每个字节进行计数。确认序号包含发送确认的一端所期望收到的下一个序号,确认序号是上次已成功收到的数据字节序号加1。
TCP的流量控制由连接的每一端通过声明的窗口大小来提供,这个值是接收端正期望接收的字节。窗口大小是一个16位的字段,所以窗口大小最大是65535字节,新的窗口扩大选项允许这个值按比例变化以提供更大的窗口。
超时与重传
对每个连接,TCP管理4个不同的定时器:
1.重传定时器用于当希望收到另一端的确认。
2.坚持定时器使窗口大小信息保持不断流动。
3.保活定时器可以检测到一个空闲连接的另一端何时崩溃或重启。
4.2MSL定时器测量一个连接处于TIME_WAIT状态的时间。