iOS知识梳理之移动开发网络篇TCP/IP

1.OSI七层 TCP/IP五层

1.1 OSI七层参考模型

应用层
表示层
会话层
传输层
网络层
数据链路层
物理层

对于OSI七层参考模型,我想说只有这七个词条.任何与实际生产脱钩的东西都需要硬性记忆.
TCP/IP五层模型我不需要硬性记忆,就可以根据应用逻辑复述出来.

1.2 TCP/IP五层模型

TCP/IP五层模型

应用层
传输层
网络层
数据链路层
物理层

TCP/IP是一组通信协议的代名词,是由一系列协议组成的协议簇.


上图是TCP/IP五层模型前四层对应的协议.(图片来源自网络,部分翻译与本文有出入)

接下来我们就按顺序来说说每一层.

2.应用层

应用层的协议有:HTTP,FTP,DNS等.他们都是有自己对应端口的,
所谓端口就是:数据由网络到达终端(手机,PC),然后交给谁.QQ聊天的数据就交给QQ,网页浏览的数据就交给浏览器.QQ,浏览器等进程都是有对应端口的.但端口分为不同类型:

IANA:互联网地址编码分配机构(Internet Assigned Numbers Authority)

熟知端口(著名端口):0-1023,由IANA指派和控制.(如:FTP:21,SSH:22,SMTP:25,DNS:53,HTTP:80,HTTPS:443等)
注册端口:1024-49151,IANA不指派也不控制,但须注册.
动态端口(短暂端口):49152-65535,IANA不指派也不控制,无须注册.通常被用来在主动发起连接时随机分配使用.

接下来我们会用HTTP,DNS来走完TCP/IP的五层结构.用这两个因为:
1.HTTP对应TCP,DNS对应UDP,这样可以囊括传输层的两个重要协议.
2.HTTP与DNS在真实的应用场景下有穿插.

2.1 HTTP


如上图所示就是我打开简书首页时用HTTP的GET方式发出的请求.(字段有些多,看上去复杂,其实我们做的只是输入一个网址,其他参数浏览器自己会配置好的)
到HTTP的各个字段全都配置好后,其实HTTP的'发'工作也就已经完成了,下面就该把数据交给传输层的TCP了.(数据传入TCP前还有个小插曲,请看2.2 DNS)

2.2 DNS

我在打开网页的时候输入的是http://www.jianshu.com/,这是域名.但在真实的网络环境下是不会用域名进行通信的.通信时数字的效率永远是最快的,这也就是IP地址(就像生活中的邮编与门牌号).

四川成都温江柳台大道555号     邮编:611130

但完全让我们这些凡夫俗子用输入IP的方式来访问网页也不现实!

www.baidu.com  119.75.217.109
www.163.com  114.80.143.193

DNS(Domain Name System)也就是一个折中.
DNS就是一个域名换IP应用协议.

这也就是上面说的插曲.HTTP请求数据准备完毕后,不是往www.jianshu.com域名上发,而是往www.jianshu.com对应的IP上发.以下就是用DNS,以域名为参数,请求对应的IP地址.


而且这个DNS请求是直接向IP地址发的,我们在终端(手机,PC)上都会配置DNS服务器的IP地址,就是用在这的.当然DNS的请求数据准备好后,其实DNS'发'的工作也就已经完毕了,数据会交给下层传输层的UDP.

以下就是DNS收到的回复:



DNS缓存:当然不可能每回用浏览器打开www.jianshu.com都要用DNS询问下DNS服务器简书的域名对应的IP地址是什么.操作系统本身有DNS缓存,浏览器自己也有DNS缓存.有兴趣请戳:主流操作系统、浏览器DNS缓存时间

3.传输层

前文说到:
DNS将数据准备好后交给UDP.
DNS收到回复,获取到域名对应的IP地址,HTTP也会将准备好数据交给TCP.

UDP与TCP同属于传输层.他们的关系就好像邮政和顺丰一样.都是快递公司,但由于工作属性,模式,态度的不一样,被不同的应用层协议所用.

TCP---传输控制协议,提供的是面向连接,可靠的字节流服务.当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据.TCP提供数据包重发,丢弃重复数据,检验数据,流量控制,拥塞控制等功能,保证数据能从一端传到另一端.

UDP---用户数据报协议,是一个简单的面向数据报的传输层协议.UDP不提供可靠性,它只是把应用层提供的数据发送出去,但是并不能保证它们能到达目的地.由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有数据包重发等机制,故而传输速度很快.

TCPUDP
正式通信前先建立连接,结束后断开连接无连接
流量控制没这回事
数据包重发没这回事
丢弃重复数据没这回事
拥塞控制没这回事

说那么多,简单些的描述就是:
TCP是面向连接,可靠的数据传输协议
UDP是无连接,不可靠的数据传输协议

接下来我们也会由连接可靠这两块来对TCP和UDP进行对比分析.

3.1 TCP

在说TCP的面向连接可靠之前,我们先来看看TCP报文段的格式,因为无论是面向连接还是可靠都依赖于TCP报文段的格式.

3.1.1 TCP报文段的格式

很清楚的能看到TCP报文段大体分为两部分:TCP首部,TCP数据部分.
HTTP的数据交给TCP就放在TCP数据部分.

TCP首部:

源端口和目的端口:上面已经说过了应用层协议都有对应的端口号(HTTP:80)

序号(seq):TCP连接中传送的数据流中的每一个字节都编上一个序号.序号字段的值则指的是本报文段所发送的数据的第一个字节的序号.

确认号(ask):是期望收到对方的下一个报文段的数据的第一个字节的序号.

首部长度:它指出TCP首部共有多少个4字节,首部长度可以在20~60字节之间.因此,这个字段值可以在5(5X4=20)至15(15X4=60)之间.

标记位:URG,ACK,PSH,RST,SYN,FIN.标记该TCP报文段的意图(如:ASK==>确认).

窗口:窗口用来控制对方发送的数据量,单位为字节.TCP连接的一端根据设置的缓存空间大小确定自己的接收窗口大小,然后通知对方以确定对方的发送窗口的上限.

检验和:检验和检验的范围包括首部和数据这两部分.在计算检验和时,要在TCP报文段的前面加上12字节的伪首部.

紧急指针:紧急指针指出在本报文段中的紧急数据的最后一个字节的序号.

选项:长度可变.TCP只规定了一种选项,即最大报文段长度 MSS(Maximum Segment Size).MSS告诉对方TCP:"我的缓存所能接收的报文段的数据字段的最大长度是MSS个字节."

填充:这是为了使整个首部长度是4字节的整数倍
3.1.2 连接
  • 建立连接,三次握手

以上就是三次握手的TCP报文段的交互,参数很多,现在只需要关注seq(序号)和ack(确认号),其他的可以先忽略不看.


ack(确认号)看的是图上小写的ack.大写的ACK是起标记作用的.

可以简单的理解为:

three times handshake

Client  [SYN=1,seq=x]==>  Server     (在吗?我要给你发数据咯)
Client  <==[SYN=1,seq=y,ack=x+1]  Server    (在的,你发吧)
Client  [seq=x+1,ack=y+1]==>  Server     (好,马上发)

这样的握手完成后就开始正式的数据交互.

正式的数据交互流程后面会说,我们现在来看看数据交互完毕后的断开连接==>四次挥别.

  • 断开连接,四次挥别

在四次挥别前,因为有数据交互,所以seq的值会比较大
Client  ==>  Server  最大seq是u-1  
1.客户端对服务器说,我传给你的最后一个数据是u-1(seq=u),我发完了,现在想走了(FIN=1),你回个话.
(FIN报文段即使不携带数据,也要消耗一个序号)

2.服务器对客户端说,你传给我的最后一个数据是u-1(ack=u+1,之前的报文段消耗了一个序号),我下一步要发送的数据是从v开始的(seq=v).
你发送完了,可是我没有发送完啊,等着让我发完!然后服务器就开始把剩下的数据给客户端.(如果服务器还有数据要给客户端的话)

3.服务器的剩余数据发送完之后,就对客户端说,我发送给你的最后一个数据的序号是w-1(seq=w),
你传给我的最后一个数据是u-1(ack=u+1),现在我的数据也发完了,我想走了(FIN=1).

4.客户端对服务器说我给你的最后一个数据是u-1(seq=u+1),我收到你的最后一个数据是w-1(ack=w+1,FIN报文要消耗掉一个序号),你可以走了.

还可以看出最后一次挥别发出后,客户端还等待了2个MSL.
MSL (Maximum Segment Lifetime),报文最大生存时间,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃.

四次挥别因为发生在正式传递数据后,不像三次握手从空白开始,所以序号和确认号会比较复杂.

3.1.3 可靠
A.数据分段
  • 缓存

在三次握手之后,TCP通信双方都为连接开辟了缓存.这里提到缓存是数据分段,流量控制,暂存乱序数据的基石.

  • 序号

为什么需要序号?因为数据传输的过程中不是'1来1回'那么简单!

在三次握手和四次挥别中,双方对发报文段,报文段是'1来1回'非常有序的.但在数据传输的过程中,并不是'1来1回'的停等作业方式,而是多发多确认的流水线作业方式.例如:

例1.先看看简单的大段数据的发送与确认

>> seq:991241 ack:1105 len>610 //发出[序号为991241,长度为610]的包
Ack<<seq:1105 ack:991851 //(注意:991851=991241+610)确认收到[序号为991241,长度为610]的包

例2.再看看多个数据包一个确认包

延迟确认:
收到对方发来的包,
同时也有数据要发给对方,就立刻发出确认包(确认包内也包含自己本身就要发的数据);
没有数据要发给对方,就等一段时间(Windows默认是200ms)再发出确认包,在这段时间内如果又恰好有数据要发给对方则立刻发出确认包.
>> seq:991241 ack:1105 len>610 //发出[序号为991241,长度为610]的包
>> seq:991851 ack:1105 len>610 //发出[序号为991851,长度为610]的包
Ack<<seq:1105 ack:991461 //(注意:991461=991241+610+610)确认收到[序号为991241,长度为610]的包 + 确认收到[序号为991851,长度为610]的包

例3.再看看更复杂的双方数据包交错的情况

通常都是发送方多个包发给接收方,接收方才有一个确认包回复,而且还会出现交错的情况.如下:

>> seq:991241 ack:1105 len>610 //send packet1
>> seq:991851 ack:1105 len>610 //send packet2
>> seq:992461 ack:1105 len>1448 //send packet3
>> seq:993909 ack:1105 len>818 //send packet4
Ack<<seq:1105 ack:991461 //receive packet[1+2]
......
简化版:
Sender send packet1==> Receiver
Sender send packet2==> Receiver
Sender send packet3==> Receiver
Sender send packet4==> Receiver
Sender <==receive packet[1+2] Receiver
......

多个包发出,一个包确认,前面已经说过了;
交错是指如上情况:发出4个包后收到的确认包只确认[1+2],而不是[1+2+3+4].

以上3个例子很好的说明了数据传输过程中发出与确认次序的错综复杂.这就要求得有序号来区分众多的报文段.

附加内容 相对序号与绝对序号:
我们用Wireshark默认看到的序号是相对序号,绝对序号通过设置也能看到.默认显示相对序号的原因是相对序号比较小,比较容易跟踪.至于绝对序号有多大,请看下面的图片,自行感受.



那么报文段的序号是如何生成的呢?

请看前面的图片TCP Cache.png.当数据在发送方的缓存中时,每个字节的数据会被分配字节号.

字节号

以字节为单位
字节号的定义范围:0~(2^32-1)
编号机制:随机
-----------
举例:
随机生成10576000个字节
字节号区间==>1057~7056

6000个字节,按每段1000个字节分为6段,每段的序号就是这段中第一个字节数据字节号.

[1057~7056]的字节分为6个报文段:
报文段1==>1000个字节==>字节区间:[1057~2056]==>序号1057
报文段2==>1000个字节==>字节区间:[2057~3056]==>序号2057
报文段3==>1000个字节==>字节区间:[3057~4056]==>序号3057
报文段4==>1000个字节==>字节区间:[4057~5056]==>序号4057
报文段6==>1000个字节==>字节区间:[5057~6056]==>序号5057
报文段6==>1000个字节==>字节区间:[6057~7056]==>序号6057
  • 分段

前面提到:6000个字节,按每段1000个字节分为6段.这只是举个例子,那么在真实的数据交互中是按什么标准来分段的呢?

这里就需要通览传输层,网络层,网络接口层的数据结构.

传输层(TCP)==>TCP报文段
网络层==>IP数据报
网络接口层==>以太帧

以太帧:RFC802.3标准规定,一个以太帧最少64字节,最大1518字节,那么去掉6字目标MAC地址、6字节源MAC地址、2字节类型、4字节CRC,
对应区间即为46~1500字节,如果不足46字节可以填充.

MTU:Maxitum Transmission Unit 最大传输单元1500字节.(太帧最大字节数1518-6-6-2-4) ==>对应IP数据报的大小

MSS:Maxitum Segment Size 最大分段大小1460字节(MTU减去IP数据报的头20字节和TCP报文段的头20字节) ==>对应TCP报文段去除20字节首部的大小

MTU的最大值是由下向上决定的.在启用巨帧(Jumbo Frame)的网络中MTU会很大(可以到9000字节),相应的MSS也会很大.但本文以以太帧的规格来讲述所有流程,特殊情况会额外说明.

通过的什么描述是不是就可以确认:一般以太网下的MSS就是1460字节.可以这么说,但真正的MSS是要通信双方'协商'产生的.

还记得TCP报文段格式中的选项字段定义了MSS吗?

TCP通信双方在三次握手的时候就已经交换过彼此的MSS了.通信双方会以双方提供的MSS值的最小值作为本次通信的MSS值.

TCP发送数据时,将大于MSS的数据分成多段(MSS一般为1460字节).

那么TCP报文段的数据部分是不是一定可以达到MSS(1460字节)?
不一定.因为TCP首部除了20字节的固定部分,还可以有多达40字节的可选信息.可选信息多一些,数据部分就要少一些,反正TCP报文段整体不能超过MSS+20个字节.

B.流量控制

还记得TCP报文段格式中的窗口字段吗?

见图TCP Cache.png,TCP的接收方是有接收缓存的.

这个窗口字段就是告诉发送方现在的接收方接收缓存最大的容量.

WSV:Window size value 接收方的接收窗口
接收方的接收窗口决定了发送方'一口气'最多能发送多少字节.发送方收到WSV后,再与自己发送出去却并未被确认的数据进行比对,来确认自己接下来发送数据量的大小.

C.拥塞控制

发送方的发送窗口是受接收方的接收窗口和网络影响的,其中限制得更严的因素起决定作用.接收窗口的影响方式非常简单,只要在包里用Win=n告知发送方就可以了.而网络的影响方式非常复杂. ------《Wireshark网络分析就这么简单》林沛满

上面的这段话很好的表达了流量控制与拥塞控制的关系.
流量控制==>顾及的是接收方的感受;
拥塞控制==>顾及的是网络大环境的感受;

  • 在途字节数

由于确认的延迟以及交错就会出现一些数据在途中.

在途字节数 = 发出的字节数 - 确认收到的字节数

  • 拥塞点

拥塞点:能导致网络拥塞的数据量;(发生拥塞时刻的在途字节数)

网络的影响方式之所以复杂是因为:

1.变化==>网络带宽是共享的,有时很挤,有时很空
2.未知==>由于是一个动态的值,网络上所有设备都不知道自己的拥塞点
3.没法通知==>接收窗口可以在包内用字段通知对方的,而自己的拥塞点是没法通知发送方的
4.瓶颈因素多==>线路上所有的路由器和交互机都可能是瓶颈

面对这么复杂的情况,没有完美的解决方案.
发送方只能维护一个虚拟的拥塞窗口,利用算法尽可能逼近拥塞点.

1.慢启动

开始发送的时候,RFC建议以2至4个MSS开始,具体个数视MSS的大小而定.
收到N个MSS的确认后,再加n个MSS.(如:2,4,8,16......)

当慢启动到达慢启动门限(ssthresh),慢启动就得转入拥塞避免.具体的慢启动门限可以定为以前发生过拥塞时拥塞点的一半.

2.拥塞避免

RFC建议一个往复时间加一个MSS(如:16,17,18......)

以上的拥塞控制都还是在非常理想的状况下,我们并未评论出现丢包的情况.接下来将会讨论丢包,出现丢包后除了数据包重发,拥塞控制也要做出相应的反应.

根据采取不同的判断条件来判定丢包,数据包重发可以分为超时重传快速重传.快速重传又因为一个优化参数衍生出快速重传加强版.我们先介绍快速重传,因为它刚好和拥塞控制的第三个状态——快速恢复有关;

3.快速恢复

  • 快速重传

超时重传的缺点很明显,我们有段时间不作为.

正常 发送与确认的流程是

接收方在收到packet1后,ack packet2的序号,表示已经收到了packet1,期待收到packet1后的包.
接收方在收到packet2后,ack packet3的序号.表示已经收到了packet2,期待收到packet2后的包.
......

而快速重传做了一点小改动:

快速重传 发送与确认的流程是

接收方在收到packet1后,ack packet2的序号,表示已经收到了packet1,期待收到packet1后的包.
接收方在收到packet3后,ack packet2的序号.表示收到了packet2后的某个包,还是期待收到packet2.(Dup Ack)
接收方在收到packet4后,ack packet2的序号.表示收到了packet2后的某个包,还是期待收到packet2.(Dup Ack)
接收方在收到packet5后,ack packet2的序号.表示收到了packet2后的某个包,还是期待收到packet2.(Dup Ack)
.......

当接受方收到的包比自己期望的序号大的时候,发出的确认为重复确认(Dup Ack).
当发送方收到的三个Dup Ack,就认定被重复确认序号所代表的包需要重传,这也就是传说中的快速重传.

>> seq:991241 ack:1105 len>610 //packet1
>> seq:991851 ack:1105 len>610 //packet2
>> seq:992461 ack:1105 len>1448 //packet3
>> seq:993909 ack:1105 len>818 //packet4
>> seq:994727 ack:1105 len>1448 //packet5
>> seq:996175 ack:1105 len>818 //packet6

Ack<<seq:1105 ack:991851 //packet1 receive,I look forward packet after packet1
Dup Ack<<seq:1105 ack:991851 //Dup Ack==> receive packet after packet2,I look forward packet after packet1
Dup Ack<<seq:1105 ack:991851 //Dup Ack==> receive packet after packet2,I look forward packet after packet1
Dup Ack<<seq:1105 ack:991851 //Dup Ack==> receive packet after packet2,I look forward packet after packet1

发生快速重传的同时,发送窗口调整为发生拥塞时拥塞点/2+3,继续走拥塞避免的流程,这个流程称为快速恢复.

附加内容:快速重传加强版

快速重传虽然比超时重传对性能有所提高,但如果细想其实是有bug的.
packet2出现丢包和packet2+packet3都出现丢包,Dup Ack的序号是一样的.这也就意味着发送方其实不知道具体丢了哪个包.在这种情况下,只能先重发packet2,在确认packet2收到后才知道packet3也需要重发.

理想的方案是接收方的包内有一个区间值,表示已经收到数据的区间.这也就是我们要说的SACK.

比如再出现packet2+packet3都丢失
Dup Ack<<seq:1105 ack:991851 SACK:993909-994726 //收到4号包,还是期待收到packet1后的包
Dup Ack<<seq:1105 ack:991851 SACK:993909-996174 //收到4+5号包,还是期待收到packet1后的包
Dup Ack<<seq:1105 ack:991851 SACK:993909-996993 //收到4+5+6号包,还是期待收到packet1后的包

这样发送方也就知道缺失的区间(即:缺哪些包);

前面已经借由快速恢复讲述了快速重传,现在我们再说说超时重传.

  • 超时重传

发出多个数据包都设置了定时器,当某个数据包在RTO(Retransmission Timeout)内没有得到确认,就判定这个包出现丢包,重传这个包.

Sender send packet1==> Receiver
Sender send packet2==> Receiver
Sender send packet3==> Receiver
Sender send packet4==> Receiver
Sender <==ack packet1 Receiver
Sender <==ack packet3 Receiver
Sender <==ack packet4 Receiver
.
.
.
packet2 timeout
Retransfer packet2

发生超时重传的同时,发送窗口调整为1,慢启动门限调整为发生拥塞时拥塞点的一半(注意不是发生拥塞时发送窗口的一半),从头走一遍慢启动+拥塞避免的流程.

总体来说,慢启动+拥塞避免+快速恢复,三者的关系可以概括为下图:


TCP的内容很多,本文无法言尽,笔者也在不断学习中.

3.2 UDP


相对TCP,UDP的数据格式和两方交互流程都非常简单.
可以简单的总结为数据交给UDP,UDP就发.

3.3 算笔帐

我们来算笔帐:
TCP==>三次握手,四次挥别,假如中间数据非常简单只有一个发送,一个确认收到.也就是说TCP一次完整的通信至少要用掉9个TCP报文段,但9个TCP报文段中的的确确是我们需要的只有两个.所以TCP==>安全+慢.
UDP==>假如中间数据非常简单只有一个发送,一个回复.也就是说UDP一次完整的通信用掉2个UDP数据报,一点也不浪费.所以UDP ==>不安全+快.

另外由上面TCP拥塞控制的分析可以看出,TCP在觉知到网络出现拥塞的时候,会限制自己的发送数据量,而UDP是没有这回事的.那么一旦网络出现拥塞,网络带宽的分配对TCP其实是不公平的.

而各个应用层的协议则会根据自己的需要选择TCP或者UDP:

TCP:
FTP
Telnet
HTTP
SMTP

UDP:
DNS
TFTP
SNMP

Although we covered reliable data transfer in this chapter, we should keep in mind that reliable data transfer can be provided by link-, network-, transport-, or application-layer protocols. Any of the upper four layers of the protocol stack can implement acknowledgments, timers, retransmissions, and sequence numbers and provide reliable data transfer to the layer above.------from Computer Networking: A Top-Down Approach, 6/e

五层模型的前四层都可以实现可靠数据传输.UDP也可以用得很安全,我开个脑洞:那就是开发者在应用层实现可靠数据传输.

4.网络层

TCP与UDP的数据殊途同归,最终都会被封装成IP数据报.

4.1 IP数据报格式


版本:比如IPv4、IPv6

首部长度:指的是首部占'4个字节'的数目,包括任何选项.由于首部长度只占4位,因此首部最长为60个字节

服务类型:包括 3位的优先权子字段 4位的TOS子字段 1位未用位但必须置0的子字段.

总长度:一共16位,理论最大长度为65535字节,但是受硬件限制,和其它方面的考虑,大部分路由器或主机支持8192字节.

标志:标识是否IP分片.第一位无用;  第二位0:允许分片,1:不允许;  第三位0:最后一片,1:后面还有分片. //[no use],[Don't Fragment],[More Fragment]

片偏移:此分片在原始数据的偏移,用于分片重组,因为13位,所以支持的最大字节为8192.

生存时间TTL:规定网络数据包在网际层传输时,代表最多可以经过路由器的个数,每经过一个路由值就会减1.
各种操作系统的默认值都不一样,xp是128,win7、unix和linux是64,也有255的.
当它为0时,数据会被丢弃,并回传一个ICMP包来通知发送者.

协议:协议字段指出此数据报携带的数据是使用何种协议,以便使目的主机的IP层知道应将数据部分上交给哪个处理过程.(如:TCP:6,UDP:17,ICMP:1)

首部检验和:这个字段只检验数据报的首部,但不包括数据部分.这是因为数据报每经过一个路由器,路由器都要重新计算一下首部检验和.

源IP地址:发送方的IP地址

目的IP地址:接收方的IP地址

数据:加入的TCP报文段或者UDP数据报

IP数据报格式中说到了几个陌生的概念:TOS,IP分片,ICMP.下面会挨个讲解

  • TOS

TOS一共8位,包括:

3位的优先权子字段
4位的TOS子字段
1位未用位但必须置0的子字段
3位的优先权子字段

111--Network Control(网络控制);
110--Internetwork Control(网间控制);
101--Critic(关键);
100--Flash Override(疾速);
011--Flash(闪速);
010--Immediate(快速);
001--Priority(优先);
000--Routine(普通).
4位的TOS子字段

0000--normal service;(一般服务)
1000--minimize delay;(最小时延)
0100--maximize throughput;(最大吞吐量)
0010--maximize reliability;(最高可靠)
0001--minimize monetary cost.(最小费用)
  • IP分片

前面已经提过:
以太帧:RFC802.3标准规定,一个以太帧最大1518字节,那么去掉6字节目标MAC地址、6字节源MAC地址、2字节类型、4字节CRC,得到IP数据报对应的MTU(Maxitum Transmission Unit 最大传输单元1500字节).
但是一个IP数据报则可能会有8192字节,超过以太帧对IP数据报的最大限制(MTU),那么这时就需要IP分片,分批进行传输.

Note:不要乱,先前说TCP数据按MSS分段,这里又说IP分片.到底这么回事啊?
TCP协议为可靠的传输协议,TCP层对数据进行分段,避免了IP分片的发生,IP分片多用在UDP协议.

IP数据报对应的MTU是1500字节,这也意味着:
TCP报文段最大1460字节;(1500-20-20,IP首部20字节,TCP固定首部20字节)
UDP数据报最大1472字节;(1500-20-8,,IP首部20字节,UDP首部20字节)

TCP自行分段,不参与分片就不多说了.
UDP的数据会一股脑的给到IP层,UDP的数据大于1472字节就会被分片.分片后再传输给接收方.

多个分片到达接收方后,又是如何重组成源数据的呢?
接收方收到标志位第三位为0的分片,代表这是最后一个分片,接收方开始根据片偏移来将多个分片重组成源数据.

  • ICMP

ICMP(Internet Control Message Protocol)互联网控制报文协议.IP层在传输数据时出现的报错都会用这个协议来通知发送方.我们平时用的ping命令也是用的这个协议.

ICMP,TCP,UDP的数据都是由IP层封装好,然后在网络中传输的,但ICMP并不与应用层有关联,所以不和TCP,UDP归为一层.

说完网络层IP数据报的格式,就该说IP地址是如何分配的,才能让数据能准确无误的到达设置了目的IP的终端设备.

4.2 IP地址的分配

以下讨论的都是IPv4,IPv6笔者也没有完全了解.

192.168.199.112

上面是我电脑的IP地址.
IP地址共32位,常以4个十进制数来书写.

11111111.11111111.11111111.11111111
255.255.255.255

那么所有的IP地址就是0.0.0.0255.255.255.255一共4294967296个,42亿多个.目前世界人口已达75亿,个人电脑、手机、大公司的服务器,42亿多个IP地址早就不够用了,所以才会有IPv6的诞生.

我们接下来会说在IPv4够用的时候,IP地址是如何分配的.

4.2.1 分类网络

IPv4够用的时候,IP地址被分为以上的五类,提供给用户的只有A,B,C类.三类地址块因为能承载的主机数不一样,为不同大小的机构所用.

  • A类

net-id范围:0~127

第0个地址块覆盖范围:0.0.0.0~0.255.255.255(保留,用作特殊用途)
第1个地址块覆盖范围:1.0.0.0~1.255.255.255
第2个地址块覆盖范围:2.0.0.0~2.255.255.255
.
.
.
第10个地址块覆盖范围:10.0.0.0~10.255.255.255(专用私有地址)
最后一个地址块覆盖范围:127.0.0.0~127.255.255.255(保留,用作特殊用途)

结论:A类地址一共有128个地址块,其中三个地址块有特殊用途,因此可以在互联网使用的地址块有125个.每个地址块可以拥有2^24个主机.
  • B类

net-id范围:128~191

第0个地址块覆盖范围:128.0.0.0~128.0.255.255
第1个地址块覆盖范围:128.1.0.0~128.1.255.255
第2个地址块覆盖范围:128.2.0.0~128.2.255.255
.
.
.
最后一个地址块覆盖范围:191.255.0.0~191.255.255.255
特殊保留地址块:172.16.0.0~172.31.255.255(专用私有地址用途)

结论:B类地址一共有16384个地址块,其中16个地址块有特殊用途,因此可以在互联网使用的地址块有16368个.每个地址块可以拥有2^16个主机.
  • C类

net-id范围:192~223

0个地址块覆盖范围:192.0.0.0~192.0.0.2551个地址块覆盖范围:192.0.1.0~192.0.1.255
.
.
.
最后一个地址块覆盖范围:223.255.255.0~223.255.255.255
特殊保留地址块:192.168.0.0~192.168.0.255(专用私有地址)

结论:C类地址一共有2097152个地址块,其中256个地址块有特殊用途,因此可以在互联网使用的地址块有2097152-256=2096896个.每个地址块可以拥有2^8个主机.
  • D类

net-id范围:224~239

用来进行多播使用
  • E类

net-id范围:240~255

保留未用
  • 特殊IP
net-id为127的地址:127.0.0.3 用于环回测试(从理论上来说只要是127打头的都是环回地址.但2个地址除外:127.0.0.0是网络地址,127.255.255.255是广播地址)
host-id位全为0:意指"网络地址"
host-id位全为1:意指网络的"所有结点" (如:128.2.255.255指向128.2网络的"所有结点")用于广播
全为0的网络地址:被保留用来指向默认路由
4.2.2 无分类网络

分类网络:A类net-id位数为8,B类net-id位数为16,C类net-id位数为24.
分类网络是无分类网络的一个特例,无分类网络就是net-id位数非常灵活.
无分类网络书写方式是140.120.84.24/20,/后跟的是IP地址的net-id位数.

4.2.3 分配子网

无论是分类网络还是无分类网络,包含主机数很大的地址块不可能在一家机构中完全铺开了使用,机构中有许多部门,所以就需要为这些不同的部门分配不同的子网.
分类网络与无分类网络分配子网的原理是一样的,以下拿分类网络的网络块举例:

C类地址块192.168.10.0,分成6个子网.

掩码很简单,就是与地址相与得到网络地址.
子网掩码就是向主机位借位,然后改变子网部分的数值,生成子网.
分成6个子网,向主机位借3位生成子网掩码:11111111.11111111.11111111.11100000



子网位全为0,是"网络地址",不能用
子网位全为1,是广播地址,不能用

4.2.4 NAT

前面已经提到目前世界人口已达75亿,个人电脑、手机、大公司的服务器,42亿多个IP地址早就不够用了.而NAT(Network Address Translation,网络地址转换)就解决了IP地址不够用的问题.

在公司电脑的IP:192.168.199.112
在家IP:192.168.199.112
其实两者根本就没关系!

就好像

上海的人民广场
不是
长春的人民广场

互联网分成公网,内网两个层级.
我们以HTTP请求为例:借助于NAT,内网IP地址(我们电脑上看到的IP)所在的"内部网络"通过路由器发送数据包时,将内网IP地址转换成合法公网IP地址(那42亿多个IP地址中的一个),同时端口号也会被换掉.如图:


然后在向公网上的服务器发出请求.服务器响应后,数据回到路由器,NAT由刚刚所用公网IP地址+端口号映射得到内网IP地址+端口号,将数据进一步传给目的主机.

这样一个"内部网络"只需使用少量公网IP地址即可实现"内部网络"内所有计算机与互联网的通信需求.

5.数据链路层

学习ing.

6.物理层

学习ing.

阅读更多
文章标签: iOS TCP/IP
个人分类: iOS知识梳理
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

iOS知识梳理之移动开发网络篇TCP/IP

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭