网络编程-网络相关的基本概念(二)

先学会不生气,然会学会气死人

这是我的第十一篇原创文章

上篇文章讲了一些文字相关的知识,虽然文字有点多,但是还有很有用的,当然这个是对于我们做嵌入式方面的来说。做应用的直接调用socket或者像andriod一样拖控件也可以实现。

好了这篇我们还是讲网络的一些基础知识,把上一篇没介绍完的继续介绍完。继续吧。

(注:这篇文章有些概念和内容来自朱有鹏老师课程和阮一峰老师的博客)

1

IP的一些相关概念

在网络传输过程中我们说的IP应该分成两个部分:源IP地址和目标IP地址。源IP地址是发出数据包网络的IP地址;目标IP地址是要接收数据包的计算机IP地址。

我们常说的IP地址实际上是32位二进制数,说白了就是一个int类型(X86)。在网络通讯中是32位2进制数,但是在人机交互中表现出来的是十进制方式。

例子:

二进制方式 0xffffffff

点分十进制 255.255.255.255

二进制方式 0xC0A80166/0x6601A8C0

(考虑大小端问题)

点分十进制 192.168.1.102

为什么要这这样子设计呢?因为点分十进制容易人看,二进制是计算机认识的。这里在PC机器内部做了一个转化。

我们的IP地址中的32位实际包括两个部分,分别是:网络地址和主机地址。

IP地址 = 网络地址 + 主机地址

网络地址: 用来表示子网

主机地址: 用来表示子网中具体某一台设备。

子网掩码,是用来说明网络地址和主机地址各占多少位。子网掩码就是用来区分什么是网络地址,什么是主机地址。在子网掩码中,为 1 的是网络地址,为 0 表示主机地址.比如:

子网掩码为:255.255.255.0;表示前24位为网络地址,后8位为主机地址。

子网掩码为:255.255.0.0;表示前16位表示网络地址,后16位表示主机地址。

2

IP地址分类

由于上面说过我们日常看到的IP地址是十进制点分形式,是由网络地址加上主机地址,二者是从属关系。我们由网络地址和主机地址所占多少位的不同,分成5类网络。

A类:(1.0.0.0~126.0.0.0)默认子网掩码为:255.0.0.0(0xff000000),这类网络地址最高位为"0",所以地址的网络号取值在1~126之间。这类一般用于大型网络。因为A类网络有126个,每个网络能容纳1亿多台设备。

B类:(128.1.0.0~191.255.0.0)默认子网掩码为:255.255.0.0(0xffff0000),这类网络地址最高位为"10",所以地址的网络号取值在128~191之间。这类网络有16382个网络,每个网络能容纳6万多个主机。一般用于中等规模的网络。

C类:(192.0.1.0~223.255.255.0)默认子网掩码为255.255.255.0(0xffffff00),这类网络地址最高位为"110",所以地址的网络号取值在192~223之间。这类网络最多可达209万个,每个网络最多能容纳254个主机。

D类:(224.0.0.0~239.255.255.255),这类网络多用于多播。这类网络地址最高位为"1110",所以地址的网络号取值在224~239之间。一般用于多路广播用户。多路广播地址被用来一次寻址一组计算机,他标识共享同一协议的一组计算机。

E类:(240.0.0.0~255.255.255.254)这类网络保留使用。这类网络地址最高位为“11110“。

5类网络中ABC三类是最常用的。D类是广播时使用,上面说到的还有几个特例.

在A组中,网络地址为1~126,还要0和127呢?其实0代表任何地址,127为回环测试地址,数字127保留给内部会送函数,而数字0则表示该地址是宿主地址。

回环测试用127.0.0.1,还有一个255.255.255.255,这个对应是的当前子网广播地址。

这里我们衍生一个问题:就是如何判断两个IP地址是否在同一个子网内?

这里有一个公式:

网络标识 = IP地址 & 子网掩码

如果两个网络标识相等,那么就处于同一个网络中。

例如:

IP_A 192.168.1.102

mask &255.255.255.0

= 192.168.1.0

IP_B 192.168.1.253

mask &255.255.255.0

= 192.168.1.0

上面的例子说明了192.168.1.102和192.168.1.253在同一个网段。

3

以太网数据包

以太网数据包只包含MAC地址,并没有IP地址的栏位。那么是否需要修改数据定义,再添加一个栏位呢?

其实是不需要的,其实他将IP数据包直接放入以太网数据包里面了,因此不需要修改以太网规格。这就是互联网分成结构的好处,上层的变动完全不涉及下层的结构。

以太网数据包的大小是固定的,为1522字节。1500字节是负载,22字节是头信息。IP数据包在以太网数据包的负载中,他也有自己的头信息,最少20字节,所以IP数据包最多1480字节。TCP数据包在IP数据包负载中,头信息最少也是20字节。加上TCP和IP协议中往往还有自己额外的头信息,所以TCP负载实际最多为1400字节左右。

(来源阮一峰老师TCP博客中图片)

为什么我们不把以太网数据包设置大一些呢? 原因在于硬件限制。如果过大,就会照成网络缓存过大,数据容易溢出,就会丢包,降低整个网络效率。然而这个还不是本质上的原因,因为在物理层协议上设计使用时钟同步相关。

包过大,也意味着在传输距离增加时,同一个信号包传输时长变长,而时钟同步信号,必须是在固定的时间中发出,为了保证这点,就必须保证MTU的大小了。

举一个例子: 例如有一个10M大小的文件,假设TCP实际负载为1400字节,那么需要发送:7000多个包。

这里就涉及到如何完整的接包进行拼接的问题了。

4

TCP数据包的编号

其实我们在发送数据的时候,TCP协议为每一个包都进行了编号(SEQ),以便接收的一方按照顺序还原。万一丢包了,也能定位是哪个包丢失。

一般第一个包的编号是随机数,为了便于理解,我们设置1为第一个包的编号吧。假设下这个包的负载是1400,那么可以推算出下一个包的标号应该为1401.就是说每一个数据包都会获得两个标号,自身包的编号和下一个包的标号。这样接受方就能知道,到时候进行封包按照这个顺序进行合成。

(图片来源阮一峰老师TCP博客中图片)

这个图片的意思是当前包的编号是45943,下一个包的标号是46183,所以这个包的大小为240个字节。

5

TCP数据包的组装

其实数据包的组装是由操作系统完成的,应用层不会直接处理TCP数据包。他只管收到完整的数据包内容(除非通讯异常)。因为TCP没有提供任何机制表示原始文件的大小,这个是由应用层的协议来规定,比如HTTP协议。

当组装好数据包的时候,就会将他们转发给应用程序。在TCP包里面有一个端口参数,就是用来指定转交给监听端口的应用程序。

6

慢启动和ACK

我们想,服务器发送数据包当然是越快越好,最好一次性把所有数据发出去的那种。但是发的过快可能丢包,带宽小,路由器过热等因素也可能导致丢包。

那我们自然就想,在数据包发送的过程中,直接到达他允许的最大值呗。但是不知道接收方的理想速率是多少,所以底层实现的方式就是慢慢的试。最开始传输的时候采用慢启动方式,比如我第一次发10个包,等待对方的ACK,查看丢包率,不丢包增快速率;自然丢包降低速率。

这里有一个ACK这个玩意,就是英文的"acknowledgement",确认的意思。

ACK里面携带的信息包括:

·下一个数据包编号

·接收方窗口剩余容量

发送方只要有这两个信息,就可以推测出接收方的接收速率,然后可以动态调整自己发送速率。

(图片来源阮一峰老师TCP博客中图片)

这里举了一个例子:由于TCP通讯是双向的,所以双方都有ACK。上图一共有4次通讯。

第一次通讯:A主机给B主机的数据包编号为1,长度是100个字节。

第二次通信:B主机的ACK标号是1+100=101。

第三次通信:A主机的数据包编号也是101,因为第二次通讯的数据包编号是1,长度为200字节,所以第三次通讯的ACK为201。

第四次通讯数据包编号就是201了

……

以此类推。

7

数据包丢失

我记得之前说过TCP是可以保证数据包的完整性的,因为每一个数据包都带有下一个数据包的标号,,如果下一个数据包没有收到,,那么ACk就不会变化。

例子:假设现在收到的是4号包,但是没有收到5号包。ACK会记录,等待5号包,如果收到5号包,那么ACK会更改,,假如没有收到5号包,那么ACK不会变化,总是等待5号包的到来。如果发送方收到三个连续的ACK,或者超时了还没有收到任何的ACK,就确认是丢包事件。从而会再次发送这个包,所以TCP能够保证TCP不会有数据包丢失。

(图片来源:阮一峰老师博客)

上图表示 Host B 没有收到100号数据包,会连续的发出相同的ACK,出发Host A重新发100号数据包。

8

一个用浏览器上网的例子

我们知道上网必要的几个条件是:有一个IP,有子网掩码,网关地址还有一个DNS的IP。有人可能会问,为什么我们电脑好像什么都没有设置为什么能上网呢?因为咱们大部分用笔记本,并且网络模式默认配置的是自动获取,再者用无线网,路由器给你分配好了IP等信息。

好,现在我们假设我们配置好了这4个上网要素,假如我们要实现上网这个过程。

2.上一篇文章说过我们DNS协议,就是将域名转化为IP的域名服务。假设我们自动获取的DNS为180.76.76.76.我们知道要通讯成功必须要有对方的IP,所以我们向DNS服务器发送一个DNS数据包,然后DNS做出响应,告诉我们一个IP地址,这才知道对方的IP.

3.接下来就是要判断我们的IP是不是在同一个子网络地址,文章有方法来判断,这里就不复述了。一般情况下不在一个Ip的。比如我们要向百度发送一个数据包,就必须通过网关来转发。

4.接下来就是数据打包的过程,将HTTP数据包,TCP数据包头,IP数据包等打包到以太网数据包内。

5.然后经过各种路由和网关的转发,百度服务器收到以太网数据包,然后根据IP标头将数据包拼接(之前说过发送数据包是有大小限制的),读取到里面的HTTP请求。

6.服务器顺着这个路由路线将HTTP响应发到本机,然后我们就能看到我们想要的网页了。

说到这里,大概将网络的一些基础东西过了一遍,写完后发现有点多。纠结了一下,多就多吧,懒得弄成两篇了,毕竟是自己的学习摘要和笔记。

这篇文章主要借鉴了朱老师上课内容和阮一峰老师的文章,还有一些网络博客。还是要表示下感谢,毕竟都是他们总结的成果。下篇可能会说下我毕设用到的乐联云的使用和写一些网络socket测试吧,那先这样吧。

-END-

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180822G1RR4I00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券