目录
前情提要
本文参考《图解TCP/IP》(竹下隆史&村山公保&苅田幸雄,著),为什么不直接看《TCP/IP详解:卷一》,是因为其他书其实都是参考那本书而来的,而且这本书岁数都比大家大,里面的东西可能有点过时,当权威的工具书来看。另外,因为非科班出身,看这一些书比较容易入门。等把这本书看明白了,再去看那本权威大作。
关于通信&组网
做嵌入式开发都知道,不同设备之间通信需要约定俗成一种通信的方式——通信协议。如果两块板卡之间采用的是不同通信协议,那么,这两块板卡之间是没办法通信的。例如有一块只支持CAN通信的板卡,和另外一块只支持IIC通信的板卡之间是不能通信的(这个不仅仅是硬件上不通还有软件上不通)。而这一个通信协议,包括了软件和硬件部分。
通信
如下图,多从机的SPI通信:
在多从机SPI通信里面,多个主从机之间通信组成了一个小的网络。主机向从机发送数据的时候,需要用到片选信号:NSS,用来告知有数据将要接收的从机做好接收数据的准备。从机少的时候可能还管用,但是从机多了就会用到很多线。
于是,就有了CAN这一类的通信方式:
在CAN总线上面,有很多机器。前面说到SPI可以通过片选信号线告诉数据接收端是谁,但是CAN没有片选信号线。CAN是通过“地址+报文”的方式来告知总线上的所有机器,其他机器根据地址确定是不是发给自己的数据(就是根据地址等具有标识性的信息辨别这一包数据是要发送给谁的?)。如果在庞大的计算机网络下,还用跟SPI通信类似的通信方式,是行不通的。那么,如何解决庞大的计算机网络下不同机器之间实现通信,让计算机网络这一门课就有了存在的意义。
组网
如果有LORA组网经验的人都知道。LORA组网,需要给每个设备一个确保在当前可以覆盖的网络下的设备号是唯一的。上述全部,几乎都是应用在嵌入式领域的(嵌入式侧重于物理端,也就是俗称的底层。而计算机网络则侧重于软件端,也就是俗称的上层。理论上,只要上层处理好,下层传输数据的话,可以转化成任何的物理通信方式。例如两台交换机之间通信中间转化成SPI通信都是可以的,只不过看有没有意义。)。那么,在计算机网络中,只要是多机器组网,就肯定需要有一个“标识”来区分每一台机器,而且确保这个“标识”唯一。于是,TCP/IP就是这么来的。
OSI模型
OSI模型是目前计算机网络通信协议的雏形,这一个模型把通信协议的功能分层处理,(类似于把一个复杂任务分成若干个简单任务)然后每一层之间通过“接口”(相互约定的协议)连接。下图是OSI模型简图:
这样的好处是,可以把整个复杂的计算机网络协议模块化,使得整个协议更加灵活(不要的层可以剔除掉),更加便于维护。另外,独立的模块通过接口连接,即使整个协议当中某一个层除了问题,都不至于影响到整一个网络通信系统。
唯一的坏处是系统过于模块化,“接口”里面的逻辑处理有点困难和麻烦。
同层通信(横向)
从OSI模型里面可以看到同层之间是可以通信的。例如下图所示:
假如应用1和应用2(或者线程1和线程2、或者进程1和进程2,后面不再赘述)是在同一个机器里面,并且是一起运行的两个线程。玩过RTOS或者Linux的都知道,这俩东西之间可以通过消息队列、邮箱、信号量等进行通信的,上图里面的“接口”就相当于这一类东西。通过“接口”,应用1和应用2实现了通信,而且是属于同一分层的通信。那么,能不能从某一个角度上看,消息队列、邮箱、信号量这一些都系都属于网络通信协议中的一部分?毕竟一个机器里面运行的不同进程之间通信也可以组成一个小网络(微观)。
不同层通信(纵向)
假如通信两端分别在两个机器上面,而且两个机器只通过一条网线连接。假如,在机器1上的应用1和机器2上面的应用2进行通信,通信数据就需要通过不同层通信到达物理层的网线上。通过网线把数据送到机器2,然后机器2再把数据一层层送到顶层的应用2。简图如下:
如上图所示,因为应用1和应用2分别位于不同的机器上,所以产生的数据只能通过接口纵向往下传递到物理层,通过网线送到另外一段。再由另外一端把数据,一层一层地进行“解析”。
实际中网络模型
到这里,应该也不难理解网络通信的模型,下面将从简单图到复杂图,从微观到宏观区看这一个模型。
(两台机器通过网线和路由器连接)
(比上一张图再增加点数量级)
(比上一张图又增加点数量级)
(从宏观上看整个结构)
上面这一些图片,展示了从微观的两台电脑之间通信结构框图,到一个国家之间的网络结构框图。再往下一层,就是全世界的网络结构了。从上面的图不难看出,不同设备之间,通过路由器和交换机作为中继站,中继站根据数据信息发送的目标地址,一步步地将数据送到目标设备里面。因为设备数量的庞大,最终把所有设备接入由路由器和交换机组成的巨大“网络”当中,从而形成了现在的“互联网”。
TCP/IP基础知识
TCP/IP用人话来说就是:网络协议族(就是用来进行网络通信的协议总称)。当然,TCO/IP协议里面包含了TCP和IP。所以说TCP/IP是两种协议也没错,只不过就有点显得不够专业而已。不过这不重要,明白这里面有什么,怎么用可以了。下图表示了,TCP/IP协议群里面包括了什么协议。注意:后面如果没有特别表明,TCP/IP指的是网络协议族。
TCP/IP分层模型
前面说过,OSI模型是目前计算机网络通信协议的雏形。所以,在TCP/IP里面就可以看到OSI的影子。
可以看到,数据通过TCP/IP协议发送出去也是一层一层加工送到硬件(物理层)的,然后通过物理层送到其他机器里面,再逐层解析,最终得到数据。
硬件、物理层
这一层,指的是网线或者无线收发器(实实在在的电路,看得到摸得着得电路板卡)等,实实在在存在的物理电路。它的内容没有固定同一的,就好像前面我说到:
理论上,只要上层处理好,下层传输数据的话,可以转化成任何的物理通信方式。例如两台交换机之间通信中间转化成SPI通信都是可以的,
只不过看有没有意义。
这部分,只要保证数据可以快速地、可靠地、安全地传输即可。因为使用不同的硬件设备,他们的传输效果不一样。TCP/IP协议就是基于这一些硬件差异提出来的一个相对统一的软件协议。
网卡、数据链路层
上一部分讲到的硬件物理层,是实实在在硬件电路。那么这一些电路是如何实现工作的,就是这一层存在的原因。这一层,也是嵌入式工程师(或者搞FPGA的、又或者芯片设计的)非常熟悉的一层(他们口中的:驱动),它是软件和硬件的边界。这一层主要负责,如何让这一些电路工作起来,并且使得数据可以发送出去和接受回来。这一层主要工作是实现怎样把数据变成1、0的逻辑电信号。
如果你是纯搞软件的,这一个你知道是什么就可以。这个内容并不在软件工程师的工作范畴之内。
互联网、网络层
在TCP/IP里面,这一层相当于OSI里面的第三层。无论是IP协议,还是ICMP协议或者APR协议,最终存在的意义、本质就是一个,前面说过的(换成人话来说):
就是根据地址等具有标识性的信息辨别这一包数据是要发送给谁的?
然后,在把数据扔给下一层把数据发出去,或者接收。
其中:
IP协议,可以看成是:网络通信的共同语言,这是网络通信的基础。首先就是让所有机器都明白,IP协议立案说的是什么东西。
ICMP协议,如果IP协议的数据包通信通信过程中发生了异常,那么,网络就会根据这一个协议告诉发送端,发生了异常。
APR协议:当数据包送到了目的机器上,这个机器就会根据APR协议对这一个数据包进行解析(解析包里面含的物理地址:MAC地址,位于以太网头部,后面会进行详细的介绍)。
所以404,算不算ICMP里面的东西?
传输层
这一层,主要实现的是:不同机器上不同应用之间的通信(同机器不同应用之间通信只需要直到接口号就可以了,不需要地址)。如果互联网、网络层给数据包赋予了机器的地址,那么,这一层给数据赋予的是应用的“地址”——端口号。
这个端口号,是用来区分机器里面不同的应用的信息。这个东西作用是:弄清楚接收到的数据是给哪个一个应用的。在这一层里面,最具代表性的是:TCP和UDP协议。
重点来了!
TCP协议,又是人们口中的“数据流”协议。是一种面向“有连接”的传输层协议。这一种协议是可以确保数据安全地、完整地发送到目标机器里面(如果中间发生了丢包,这一包数据就会重发,直到没有丢包为止。此外,这一种协议也防止数据发生“串包”,不同包的数据混在一起打乱了)。所以从建立连接,到结束连接,至少需要7次通信。也就是,3三次握手和4次挥手,具体原理后面再说。就是因为这种协议具有很不错的安全性,所以就要相对应牺牲一点资源,所以实时性差了一点。
UPD协议,是面向“无连接”的传输协议。它不会关注接收端是否完整收到有效数据。它只管把数据打包然后往目标砸(打包完成直接发送),以至于数据有没有“砸坏”,它是不管的。所以这个协议通信的时候实时性非常好,就是很有可能丢包而已。不过没所谓,这种协议一般用在语音或者视频通信上,数据丢包顶多就是掉帧而已。另外,这一种协议广泛用于广播。
应用层(会话层以上的分层)
参考OSI模型,TCP/IP把会话层,表示层,应用层合为一体统称为应用层。在这一层里面,所有功能都是由应用程序实现的。这一些功能有可能由当一个进程实现,也有可能是由多个进程实现。在TCP/IP协议里面,绝大多数框架都是客户端/应用端的模式。提供服务的叫服务器,接收服务的叫服务端。这一种情况下,一般有一个专用机子(服务器),里面主要跑一个进程,然后等待客户发送的请求。
所以,服务器本质上也是一个电脑,那么它也有电脑的结构。不难理解,为什么多人同时在线的游戏为什么会炸服务器。因为服务器里面用于暂时存放数据的缓冲区被请求塞满了,服务器处理速度跟不上,结果数据发生了“堵车”,然后掉包的掉包,掉线的掉线。
WWW(web)
这一个东西,就是一般网址前面的那一块东西。点开一个网站,就是典型的:浏览器这一个应用和对应网址服务器的通信。浏览器和服务端之间通信,使用的就是HTTP协议,里面传输的内容(文件),都是基于HTML格式的。所以你把一个网页保存下来,看到文件命后缀都是.html的。那么,在浏览器看到的网页,就是你的电脑浏览器向服务器发送一个请求,然后服务器给你发送了一个HTML文件,然后浏览器收到了这一个文件,把它显示出来。
电子邮件
这一个东西,最最原始的模式是:发送端和接收端都是开机的,打开同样的应用,然后两个同样的应用之间相互发文档。我觉得这个才是网络通信的原始状态,几乎所有都是基于这一个东西演化出来的。但是,现在你发一个邮件,总不能等到别人“上号”你才能发送。现在只是把上一部分说的框架模式改了一下而已。
机子1,先把邮件发给邮箱服务器暂时保存。过了一段时间,机子2上号了,给邮箱服务器发送请求,问有没有邮件,然后服务器给机子2砸了一封邮件。同样,你把邮箱服务器换成网盘服务器、聊天服务器,一样说得过去。(宏观上面看都是一样的)
FTP
例如:把机子1上D盘的一个文件转移到机子2上E盘(或者其他盘)的意思。可以参考我前面写的里面的uboot启动内容。
通俗地、有效地学习Linux驱动&应用(只要没更完有空就更)
远程登陆SSH\TELNET
懒得描述了,玩过树莓派的应该了解到这个是怎么一个玩法。或者你人在家,电脑在公司,远程遥控。
网络管理SNMP
你修改你家WiFi密码可以体验这个过程。
协议软件结构
上一部分主要讲了TCP/IP硬件上是如何实现数据传输的。这一部分主要讲述,TCP/IP协议主要是怎样处理数据流的。
数据包结构
从应用层到传输层,再到网络层。数据每经过一层,就会被添加一个头部。这个头部里面包括了地址,协议方式,端口号的信息。具体简图如下:
可以看到本层会把从上一层收到的数据包看作本层的数据,再加上本层的数据头部。当数据到达了数据链路层,会在加上以太网首部的同时,在数据包尾部加上以太网校验尾部。
流经数据链路的包(收发过程实现)
下图是每一组数据,流经整个链路的全过程,从中可以知道接收和发送的过程是如何实现的。
在以太网头部,给位按顺序分别是:接收端的MAC地址、发送端MAC地址、下一段协议类型。在网络层头部,各位按顺序分别是:发送端IP、接受端IP、下一段协议内容。在传输层,各位按顺序分别是:源端口号(是从哪个应用发出的)、目标端口号(到哪个应用里面去)。然后,再到数据和以太网校验。发送过程是给数据加入头部,接收的过程是给数据解析头部。
那么,要通过网络发送TCP/IP类型的数据,除了要直到自己的信息以外。还需要知道:目标的MAC地址、目标的IP地址、目标的端口号这三个信息,才可以完成数据的从传输。那么不同头部需要用不同的协议解析:
头部 | 以太网头部 | IP头部 | 传输层 |
对应解析 | APR解析以太头部里面MAC | IP协议解析IP头部里面的IP地址 | TCP/UDP等解析出端口号 |
需要注意的是,物理地址MAC是指设备唯一的身份标识,另外,只有接入网络的设备才会拥有IP地址。也就是说,IP地址虽然唯一,但是可以更换,而MAC是写死的(虚拟机从除外)。
下图是各层收发处理的回路简图 :
数据链路
这一部分主要讲OSI模型里面的数据链路层。数据链路层里面,就是你们熟知的网口、网卡、物理层的同称,也就是硬件。没有这一些硬件支撑,这一些TCP/IP协议无从谈起。
数据链路层种,不同通信媒介相互协定一种数据传输规范。通信媒介包括:电缆、光纤、电波或者红外。在计算机中普遍使用二进制表示信息,在这一些媒介,通过高低电平和强弱(亮灭)光照表示“1”和“0”。本部分将会涉及到一些链路层的技术:MAC寻址、介质共享、非公有网络、分组交换、环路检测、VLAN、以太网、WLAN、PPP等。
MAC地址
前面说过MAC地址是设备唯一的地址,理论上是不会变的,用于识别数据链路中相互连接的节点。(令牌环:FDDI)
关于MAC的格式大致如下:
因为网卡在生产时,会把MAC地址烧写到ROM里面,因此为了遵循地址唯一的原则,每个网卡的MAC都是唯一的。
MAC协议结构
下图是MAC地址的组成简图:
一共48bit,再分6位,每位8bit,即1字节。然后每个字节转化成16进制为一位。组成了:
XX:XX:XX:XX:XX:XX的形式。
再数据链路层中,数据都是一位位传递的。根据不同的规范(IEEE802,IEEE美国电器和电子工程师协会),有如下方式:
数据本质上没变,只是在数据发送的时候数位先后顺序改变了。根据所使用的协议,可以解析出MAC地址。标准详解如下:
1)IEEE 802.3 :以太网介质访问控制协议 (CSMA/CD)及物理层技术规范。(没规定哪一种链路)
2)IEEE 802.4 :令牌总线网(Token-Bus)的介质访问控制协议及物理层技术规范。
3)IEEE 802.5 :令牌环网(Token-Ring)的介质访问控制协议及物理层技术规范。
4)IEEE 802.6 :城域网介质访问控制协议DQDB (Distributed Queue Dual Bus 分布式队列双总线)及物理层技术规范。
所以,IEEE802.3制定MAC地址规范时候,没有限定链路类型,即在不论哪一种数据链路下,IEEE802.3不允许有相同MAC出现。
根据MAC地址转发数据
在共享介质网络里面,同一时间只有一台机器在发送数据,当网络中机器数量增加时,工作效率会大幅降低。在应用以太网交换机的时候,交换机会根据链路层每一帧数据大的MAC地址决定数据从哪一个接口转发出去,这个时候用于参考、记录发送接口的表叫转发表(Forwarding Table)。这一个表并不需要人工设置,它可以自动生成。这个表开始为空的时候,可以广播MAC地址,然后看哪一个接口有回应,对应就是该MAC的接口,然后一步步第填满这个逻辑表格,这一个过程也是自学的过程。
共享介质网络
共享介质网络,简单来说就是所有机子都要一条线上面(所以前面的令牌环,以太网都俗语此类网络)。在共享网络里面,有两种访问控制方式:争用&令牌。
争用
网络中,各个站点采用先到先得的方式对网络进行抢占(CSMA,载波监听多路访问)。如果多个站点同时发送数据帧,则会导致数据冲突,造成数据拥堵。
后来,有人对这种方式进行了改造,变成了:CSMA/CD。CSMA/CD要求每个站点提前检测是否冲突,如果发生了冲突,则尽快释放通道。
工作原理如下:
1、如果载波信道上没有数据流动,则任何站点都想发送数据。
2、检测是否发生冲突,一旦有冲突,放弃发送数据,同时释放信道。
3、放弃发送以后,延时一段时间再争夺介质。
令牌
令牌传递方式是一种在环状网络里面使用的通信方式。如下图所示:
在令牌环里面,不同机子当中发送着一个“令牌”报文,是控制传输的一种方式。只有获得令牌的机子才可以发送数据。这一种方式有两个好处:一是不会有冲突,而是每个机子都拥有平等的通信机会。即使数据拥堵,也不会造网络性能下降。
但是,这样的链路里面,一个机子没有收到令牌是不可以发数据的,即使在数据不拥堵的情况下,数据利用率也不能达到100%,于是衍生出多令牌传递技术。
非共享介质网络
非共享介质网络,通俗来说是:所有机子都不在同一条网线上面。这一种工作模式下,所有设备通信都需要网线连接交换机进行工作(很多情况下都是双工的)。每一个站点都连接交换机,所有数据统一由交换机转送。
通过交换机,不同的以太网之间可以构建成更大的网络,这一种结构也是被广泛应用的。因为一台机子占用一条线,也就不用考虑数据冲突的问题。不过该方式有一个比较致命的缺点,就是只要一个交换机出了故障,整个局域网就会不能工作。
环路检测
因为网络拓扑结构的原因,很不幸常出现了环路,导致数据一直被转发。解决这一个问题有两种方法:1、生成树。2、源路由。
生成树
这一种方法源于IEEE802.1D(因为这个用时太长,大越十几秒。在IEEE802.1W里面定义了RSTP的方法,把用时缩短到几秒内)。每个网桥需要在1~10秒内交换一个数据包——BPDU(Bridge Protocol Data Uint),用于判断哪些端口是否需要工作,以便消除环路。一旦发生故障,自动切换信道,利用没被使用的端口传输数据。例如以某一个网桥为构造树的根(root),并且对每一个端口设置权重。这一些权重可以人为设定,指定优先使用哪一些端口用于在发生故障时候可以继续工作。
如上图所示,成产生了环路就会有机器在两个端口收到一样的数据,这样机器判断这两个端口发生了环路,就不会让这帧数据从这两个端口发出去。
源路由
最早是为了解决令牌环的环路问题提出的。这个方法可以判断数据传递的源地址是通过哪一个网桥的,并且把信息帧写入RIF(Routing Information Filed)。网桥根据RIF里面的信息,判断发送地址,即使出现了环路,数据也不会被反复转发。这种机制中,发送端必须具备源路由功能。
VLAN
在进行网络管理的时候,时常遇到分散网络负载、变换部署网络设备位置等情况。这时候人们可能就需要对物理网络结构进行改造,但是使用VLAN则不需要动网线。这样做,可以使得网络利用率提高(例如下图B网段的两机器之间通信频率极高,直接划分一个网段给两台机器)。
A网段和B网段之间通信,采用了IEEE802.1Q的标准(也叫TAG VLAN),该标准允许包含跨异构交换机的网段。TAG VLAN对每一个网段进行唯一标识,交换的时在以太网头部加入VID标签,然后后续机器根据这个VID发送给目标网段。
以太网
以太网最早是Xerox(美国)和EDC(美国)公司设计的一种通信方式,但是命名为:Ethernet。后来IEEE802.3间其规范化,两者还是不同的(所以分为了以太网、802.3以太网)。前面讲到了链路层里面的通信结构,以及MAC地址。在这里,讲一下链路层使用最广泛的通信协议——以太网。然后下面是回顾前面讲到的TCP/IP结构示意图(例子是以太网,不是802.3以太网):
就是,目标MAC、源MAC、类型三部分组成了以太网的头部。换句话说,是以太网头部带着数据在网络中寻址,当找到目标MAC的端口,就把数据送进去。所以,MAC是以太网头部的一部分。
以太网连接形式
以太网开始普及的时候,多个终端还是采用共享介质的方式连接在一起。后来就使用独占式电路和交换机连接,提高工作效率。
以太网分类
以太网因为线缆通信速率不同,被分成了不同类别。如下图所示,
例如10BASE中的“10”、100BASE中的“100”、1000BASE中的“1000”、10GBASE中的“10G”分别指的是传输速度:10Mbps、100Mbps、1Gbps、10Gbps,后面追加的:5、2、T、F等等是传输介质。当传输速度相同,但线缆种类不同时,可以使用允许变换介质的中继器或者集线器。如果传输速度不同的话,则一定要使用变速设备如网桥、交换集线器、路由器。
以太网帧格式
以太网传输数据的时候,头部前面还有一串引导码(8个8位字节)。这一串引导码由1、0交替组成,,表示一个以太网帧的开始,也是对端网卡保持与其同步的标志,在最后一字节的尾部以11结束,后面则是数据帧本体。
下图是以太网数据帧示意图,包括IEEE802.3:
类型帧一般跟着数据一起传输,它表示了再上一层网络协议类型。在这一帧里面可以存放以下数据:
尾部的FCS用于校验,如果校验结果和FSC一致,则可以使用该数据(数据端整段的CRC校验和)。
在802.3里面,加入了帧长度、LLC、SNAP。其中SNAP里面标识的也是上一层协议类型(内容与以太网协议类型基本相同)。如果使用了VLAN,那么它的帧结构也会不同:
上图,IEEE208.3里面的LLC(逻辑链路控制层)和SNAP就是逻辑链路控制的头部信息。假如类型里面为:05DC,表示为802.3Ethernet的长度。而上层信息只能在LLC和SNAP里面找到。
无线通信
采用电磁波、红外线、激光灯方式进行数据传播,一般在小空间内组成的较高速局域网被叫做无线局域网。
无线通信种类
根据IEEE802指定的规则,定义了以下几种无线标准:
IEEE802.11
IEEE802.11定义了无线LAN协议中物理层和数据链路层的一部分(MAC层),IEEE802.11这个编号有时候指的是众多标准统称。在MAC层物理地址与以太网相同,都是使用MAC地址,而介质访问控制上则使用CSAM/CD(争用)相似的CSAM/CA方式。
在IEE802.11里面,有分为了好几个标准:IEE802.11b、IEE802.11g、IEE802.11a、IEE802.11n等,它们本质区别是频段和传输速度不一样。
其他通信方式
除了一般的wifi(无线LAN),还有蓝牙、WiMAX以及Zigbee一共四种。它们最主要区别就是频段、传输速率以及功耗不一样,在这里,Zigbee的功耗是最低的。
PPP
PPP指的是点对点,即1台机器对另外1台机器通信的协议,PPP相当于OSI的第二层链路层。PPP需要与第一层:物理层相关,PPP纯粹是链路层和物理线路并没有关系(就是要实现PPP通信还需要物理层支持)。
LCP与NCP
在开始进行数据传输前,先要建立一个PPP级的链接,这个链接建立以后可以用来进行身份确定、压缩和加密。在PPP里面,包括两个协议:一个是不依赖上层的LCP和一个依赖上层的NCP。如果上层是IP,此时的NCP也叫IPCP。
PPP帧格式
PPP数据帧格式如下:
其中,标志码用来区分每个帧。因为PPP是基于HDLC(高级链路控制)的一种协议,所以和HDLC一样,在每一帧前后加上一个“011111110”的标志码。 在两个标志码之间,不允许出现连续6个以上的“1”。因此在发送帧的时候,当连续出现5个“1”的时候,后面必须插入一个”0“。如果接收端收到连续5个“1”的时候,且后面跟着全是”0“的时候,这一帧数据就不能要。
因为这一种通信方式要在软件里面实现,所以增加了机器本身工作量。
PPPoE
有些服务商在以太网上利用PPPoE提供PPP功能。因为ISP的普及,所以采用PPPoE管理以太网(单纯的以太网没验证功能)。下面是PPPoE的数据帧格式:
IP协议
IP(Internet Protocol)协议,作为TCP/IP里面重要的一层,主要负责将数据包送到目标机器上。所以,基本上世界上任何两台机器都可以通过互联网相互通信。
IP即网际协议
TCP/IP协议最主要大的一层是互联网层,这一层主要由Internet Protocol和Internet Control Message Protocol两个协议组成。这里暂时只对IP协议进行详解。IP即网际协议相当于OSI模型的第三层,主要完成终端之间通信(也叫点对点通信)。如下图所示:
IP基础知识
IP里面大致包括了三个作用模块:IP寻址、路由、IP分包和组包。
IP地址
IP地址属于网络层的地址,需要有一个类似于物理地址的标识码进行识别。作为网络层的IP,也有地址信息供识别,其作用是:连接到网络中的所有主机中识别出进行通信的目标地址。所以在网络协议族里面,每个机器都需要自己设定IP地址。
首先,IP地址的格式是固定的,然后在物理层以及数据链路层层不需要设置IP地址,它们只负责把数据转换成“1”和“0”发送出去。
路由控制
指的是将分组数据发送到目标地址的功能,即使网络非常复杂,也可以通过路由控制确定送达目标的路径。
跳,指的是每个网络之间的跳转,每个区间内决定着包下一次条向的路径。
路由控制表,是每个主机里面都有的一张路由控制表,记录着IP数据下一步发送到哪里。
IP地址结构组成
IP地址由网络地址和主机地址两部分组成,而且要求在每个网段里面,每个机器的主机标识不一样。
IP的分类
IP地址分为四个类别:A\B\C\D四类,简图如下。A类首地址以0开头,从1到8位是它的网络标识符。B类是以10开头,从1到16位是它的网络标识符。C类是以110开头,从1到24位是它的网络标识符。D类是以1110开头,从1到32位都是网络标识符(没有主机标识),用于广播。
广播(单次)
广播分为直接广播和本地广播两种。其中,本地广播是在同一网段里面广播,而直接广播,是在其他网段里面进行广播。如下图所示:
多播(多次)
多播使用的是D类IP,所以只要是开头为:“1110”的数据帧可以认为是多播。如下图所示:
由上面可知,从224.0.0.0到239.255.255.255都是多播地址的可用范围。其中从224.0.0.0到224.0.0.255不需要路由控制,在同一网段实现多播(给同一网段的所有机器发送数据包)。下图是既定的多播地址(支持IGMP协议):
路由控制
发送数据包的时候,所使用的地址是网络层的地址,即IP地址。但是仅靠IP地址是无法把数据送到目标机器的,所以在发送过程中,还需要“指明路由器和主机的信息”——路由控制表(前面讲过)。关于路由控制表,一可以由人工手动设置,二可以由路由器自己生成。下面是自动生成路由控制的原理示意图:
当一个路由器又来了路由控制表之后,就可以这样工作。根据IP的内容,决定把数据往哪一个端口里面送。
IPV4
通过IP进行通信时,需要在数据前面假如IP的头部信息(在这个头部里面包含了关于IP的一切必要信息),了解IP协议的头部信息,就可以解读整个IP协议。下图是IPV4的报文格式:
在上图,解读了IP协议大的头部信息。其中:0~3位为版本号,例如IPV4版本号为:4。在这四位为:0100。4~7位为首部长度,表明了这一个头部有几个字(1字=4字节=32bit),例如没有可选项的IP包,首部长度设置为5(“0101”)。8~15位DSCP\DCN段,前身为区分服务(TOS),由1字节标识,用于表明服务质量,但是因为效率太拉了后来就变成了DSCP\DCN,具体如下:
(区分服务)
DSCP段是TOS的一部分,现在统称为DiffServ,用来进行质量控制。ENC用来报告网络拥堵情况,由两个bit组成。
如果网路出现了拥堵,CE会置1,如果需要处理ECN,则ECT置1。
总长度,指的是整个包的长度。标识,指的是这个包是第几号包。标志,标识包被分片信息,内容如下图:
片偏移,用来标识分片数据相对于原来的位置偏移了多少位。生存时间,表示可以经过路由器个数,每次经过一个路由器,这个数就会减少1,当合格数为零的时候,该包销毁。协议,指的是下一层是进行什么协议。首部校验和(和校验),由两个字节组成,只校验首部,不校验数据部分。源地址、目标地址各32比特。可选项,长度可变,用于试验和正端。填充补零。
IPV6
下图是IPV6的格式简图:
相比于IPV4有了很大改变,为了减少IPV4的负担,缺省了校验和。为了64为计算机更方便处理,首部(不计地址)和可选项都为2字(8个字节)。
和IPV4一样,0~3bit一共四位表示版本号。因为TOS在IPV4里面使用不广泛,在IPV6里面变成了通信类型TC,也是占8个bit,4~11位(内容和Diffserv一样)。流标号由20bit组成,用于QoS(质量服务)使用,不用的时候全部设置为0。有效载荷长度,存放数据长度,相当于IPV4的TL。如果IPV6下有可选项,则长度包括可选项,没有的时候则不包括。下一个首部,占16~24位,通常表示上一层是TCP还是UPD。跳数限制,和IPV4一样。源地址和目标地址都是128个bit(一共8个16字节)。
此外,IPV6可以添加多个首部扩展。
TCP与UDP
TCP和UDP是位于传输层的协议,这两个协议具有广泛的代表性。其中,TCP主要用于可靠性的传输,而UDP主要用于广播,以及高实时性场合。
传输层定义
在前面说过,IP首部有一个字段用于描述IP的再上一层是什么协议,根据这一个字段可以知道后面跟着的是TCP还是UDP。同样,传输层的TCP和UDP为了识别发给哪一个应用,也设定了一个编号。
通信处理
在TCP/IP众多应用协议里面大多数以客户端/服务端形式运行。作为服务端的程序有必要提前启动,准备接受客户发过来的请求。否则客户发送请求过来也无法做出回应。
传输层TCP/IP协议通过接收数据中的目标端口号识别目标处理程序。
TCP和UDP区别
前面说过,如果需要可靠的数据传输,则使用TCP协议。如果需要广播或者要求高实时性,则使用UDP传输。没有说哪个好哪个坏,只有说哪个合适,哪个不合适。
套接字socket
关于很多人口中所说的套接字,就是应用和TCP和UDP之间连接的API接口。当前,它们在不同语言下面已经有完整的库函数可以调用。应用程序利用套接字,可以修改对端IP、端口号,并且实现数据的收发。
端口号
在数据链路和IP中的地址,分别指MAC和IP地址。前者用来识别同链路中不同计算机,后者用来识别TCP/IP网络中互联的主机和路由器。在传输层也有这样类似的标识,就是端口号。
端口号和应用
一台计算机上面,可以同时运行多个程序。例如接受www服务器的web浏览器、电邮客户端、远程登陆ssh等。传输层协议正式利用这些端口号识别本机中进行通信的应用程序。
有时候,打开的应用端口号都是一样的,但是其源IP地址,或者通信协议不一样,也会认为是两个不一样的通信。
UDP
UDP不提供复杂的控制机制,利用IP提供面向无连接的通信服务。并且它是将应用程序发来的数据在收到的那一刻,立即按照原样发送到网路上的机制。即使是出现在网络拥堵的情况下,UDP也无法进行流量控制等避免网络拥堵的行为。此外,传输途中即使出现丢包,UDP也不会重发。
UDP首部
下图所示,是UDP的首部结构图:
源端口号,指的是发送端的应用端口号。目标端口号,指的是接收端的应用端口号。包长度,里面存放了UDP的首部长度和数据长度之和。
校验和是为了提供可靠的UDP首部和数据而设计的。发送端和接收端通过构造一个UDP伪首部,然后在这个UDP首部里面,每16bit进行1的补码。得出四个补码数值之后,计算出它们的和,则为校验和字段的内容。
如果不进行校验和,则在该字段全部写入“0”即可。
TCP
在TCP里面,为了确保数据的准确性,会对数据传输时实行各种控制功能。可以对丢包数据重新发送,也可以对次序混乱数据进行排序。因此,TCP是一种面向有对象的连接协议,只有确定通信对存在时才会发送数据,从而可以控制通信流量控制。
TCP首部
相比于UDP,TCP首部显得复杂更多,下面是TCP首部简图:
在TCP首部里面,和UDP一样,有源端口号和目标端口号。序列号,指的是发送的数据是第几帧数据(数据序列号)。确定应答号,指的是接收端返回的下一次应该收到的数据序列号。数据偏移,指的是TCP发送的数据应该TCP包的几位开始读取。保留,指的是为后续扩展使用的数据位,一般全部填入零。控制位,字段长8bit,其每一位对应的内容从左到右分别为:CWR、ECE、URG、ACK、PSH、RST、SYN、FIN。
CWR:
和ECE都用于IP首部的ECN字段,ECN标志位1时,表示已将拥塞窗口缩小。
ECE:
置1的时候,表示从对方到这里的网络有拥塞。
URG:
为1时,表示该数据包有紧急数据处理。
ACK:
为1时,表示应答字段变成有效。TCP协议规定除了最初建立连接时候的SYN包之外该位必须设置为1。
PSH:
为1时,表示将收到的数据立即上传到应用层。为0时,则不需要立即上传,可以先进行缓存。
RST:
为1时,表示当前通信有异常,需要强制断开。
SYN:
用于建立连接,SYN为1时,表示希望建立连接,并在序列号的字段进行序列号初始值的设定。
FIN:
为1时,表示希望断开连接,用于断开连接。收发两端可以相互发送一个FIN有效的TCP协议包。但是不用立刻发送,可以等缓存里面的数据全部发送再发送一个FIN有效的数据包。
窗口大小,该字段为16bit,用来告知从相同的TCP首部确认应答号所指定位置开始能够接收的数据大小(就是数据长度不能大于这个窗口尺寸,单位:字节)。校验和,和UDP一致,只不过无法关闭。紧急指针,为16位字段,只有URG为1时才有效,该字段指出数据包哪个位置数据是紧要的,需要立即处理。选项,最大为40字节,根据数据偏移进行控制。
三次握手与四次挥手
前面讲到,TCP需要在确定进行了有效的连接之后才开始发送数据。那么,在这一个过程里面,收发端实现“握手”和“挥手”的过程如下:
在这里,需要知道两个东西:序列号和而应答序列号,这两个是不同的。在连接刚刚建立的时候,应该这样:
round1:
客户端发送一个TCP包,SYN=1,并且序列号随机生成一个数a,然后给服务端。
round2:
服务端收到了客户端发送的数据包后,返回一个TCP包,SYN=1,ACK=1,并且序列号随机生成一个数b,并且应答序列号变成a+1。
round3:
客户端收到数据包之后,返回一个数据包,ACK=1,序列号=a+1,应答序列号=b+1。
这样就完成了三次“握手”,然后开始通信。
当需要断开连接的时候,也要进行四次挥手,具体过程如下(假如中间进行了来回100次通信,接着上一次):
round1:
客户端发送了一个TCP包,FIN=1,ACK=1,序列号=b+100,应答序列号=a+100。
round2:
服务端收到了客户端的数据包之后,返回一个数据包,FIN=0,ACK=1,序列号=a+100,应答序列号=b+101。
round3:
服务器开始发送断开TCP包,FIN=1,ACK=0,序列号=a+101,应答序列号=b+101。
round4:
客户端收到服务端的断开TCP包之后,返回一个数据包,FIN=0,ACK=1,序列号=b+101。在这时候,应答序列号已经不重要,本应该是a+101的。
这四步完成以后,通信断开,完成了四次挥手。
TCP的有序有效通信流程
在TCP里面,正常的数据包通信是由一个个应答回合组成的。就是发送端每发送一个包,接收端收到之后都会返回一个应答。例如下图:
如果中间发生了丢包,错误包,机器会在超过指定时间之后再次发送相同的数据包,例如下图:
或者是这样:
重发超时
重发超时指的是,若发生接收端没回应,等待应答时间到达了某一个时间间隔的时候,发送端将会重新发送。因为网络环境的复杂性以,长距离和短距离发送数据,拥堵和不拥堵发送数据用时是不一样的。所以,TCP在每次发送数据包的时候去计算用时。
用时=往返时间+偏差
如果发生了超时,则:
用时=往返时间+偏差+重发超时时间
这个数值比总和稍微大一点点。
(因为每次通信的路线可能不一样,因此会有偏差出现)
在很多系统中,一般以0.5秒为一个超时单位。但是对于首次发送数据不知道来回用时,发送端会给6秒的等待时间。假如,6秒之后还是没受到回复,则再次发送,等待时间会以2、4.....倍被延长。但是当重发、等待次数达到一定时并还没受到回复,发送端会判定网络有问题。
TCP以段为单位发送数据
在建立TCP通信的时候,也要,也必须确定好一包数据有多长。这里称它为:“最大消息长度”(MSS:Maximum Segment Size)。最理想的情况是,长度正好是IP中不会被分片处理的最大数据长度。也就是发送端平时发送一包数据的长度小于MSS,可以放的进去。但是,不同机器发送数据包长度不一样,这需要收发双方在第三次握手的时候协定好,一般协定双方最小的的长度。
利用窗口控制提高速度
TCP以一个段为单位发送数据,然后等回复。这样有一个缺点,就是占用时间长。为了解决这个问题,TCP会用更大的分段来进行确定,转发时间大量缩短。对于发送端来说,不用一直等待回复,而是可以连续发送。
窗口大小指的是:前面讲的数据分段,发送端无需等待回复的最多分段数。如上图所示,这个窗口大小为4个分段。这个机制实现了一定的缓冲功能和多段应答功能。
滑动窗口
如下图所示:
假如以4个分段为窗口大小。当缓存区里面,发送端收到了接收端2001的应答,则发送端的发送缓存区往前送一格(也就是说可以释放1001到2001的缓存空间了)。可以看到发送端的发送缓冲区的窗口时可以滑动的。
窗口控制与重发控制
如果在窗口里面,发生了数据丢失。
在这里,先讨论应答丢失:
我们知道,接收端在收到数据之后,都会回复下一段首位序号,假如回复原来一段的首位序号,则发生了发送端丢失。在一个窗口之内,假如前面的应答发送都丢失了,但是最后一个应答接收到了,而且序号对的上,则说明前面丢失的回复都是收到的。
发送端丢失:
假如一个窗口里面,某一段数据丢失了,接收端会回复三次该段数据首位序号,与此同时,发送端还会继续发送。当发送端受到了三次同样的回复,则重发该段数据,然后接收端收到以后,继续往下发送。
拥堵控制
如下图所示:
在拥有窗口控制之后(窗口大小的调节),TCP通信不再是一段段通信。在同一个网络里面,有很多机器同时进行通信。假如,在不清楚当前网络环境的情况下,直接开始大批量数据传输,可能会引发拥堵,网络瘫痪等等。在这种情况下,第一次通信的窗口只有一段,然后逐次增加,直到出现延时之后不再增加(这个叫慢启动)。
增加过程如下:
拥塞窗口越大,应答数目也会增大。不过每收到一个应答,窗口大小涨幅也会变小。刚开始通信的时候,不会设置一个慢启动阈值,当出现拥堵时候,才设置出现拥堵的时窗口大小的一半。然后窗口大小设置为:慢启动阈值+3的数值。