每一台电脑都有主机号,主机号部分的比特全部为0或者全部为1时代表两种特殊的含义。主机号部分全部为0代表整个子网而不是子网中的某台设备。此外,主机号部分全部为1代表向子网上所有设备发送包,即广播。IP地址的主机号全0:表示整个子网全1:表示向子网上所有设备发送包,即“广播”
DNS 域名解析
对于DNS服务器,我们的计算机上一定有相应的DNS客户端,而相当于DNS客户端的部分称为DNS解析器,或者简称解析器。通过DNS查询IP地址的操作称为域名解析,因此负责执行解析(resolution)这一操作的就叫解析器(resolver)了。
下面是DNS服务器解析的流程:
DNS解析器发送消息这个操作并不是由解析器自身来执行,而是要委托给操作系统内部的协议栈来执行。
向DNS服务器发送消息时,我们当然也需要知道DNS服务器的IP地址。只不过这个IP地址是作为TCP/IP的一个设置项目事先设置好的,不需要再去查询了
客户端向DNS服务器请求时包含了域名,class,记录类型
class:在最早设计DNS方案时,DNS在互联网以外的其他网络中的应用也被考虑到了,而Class就是用来识别网络的信息。不过,如今除了互联网并没有其他的网络了,因此Class的值永远是代表互联网的IN
记录类型:表示域名对应何种类型的记录。例如,当类型为A时,表示域名对应的是IP地址;当类型为MX时,表示域名对应的是邮件服务器。对于不同的记录类型,服务器向客户端返回的信息也会不同
在域名中,越靠右的位置表示其层级越高,比如www.lab.glasscom.com这个域名如果按照公司里的组织结构来说,大概就是“com事业集团glasscom部lab科的www”这样
DNS服务器查询流程:
一台dns服务器可以存放一个或多个域,但是不能将一个域分开放到不同服务器。www.baidu.com中,www,baidu,com是三个域
在互联网中,com和jp的上面还有一级域,称为根域。根域不像com、jp那样有自己的名字,因此在一般书写域名时经常被省略,如果要明确表示根域,应该像www.lab.glasscom.com.这样在域名的最后再加上一个句点,而这个最后的句点就代表根域。
根域的DNS服务器信息保存在互联网中所有的DNS服务器中。这样一来,任何DNS服务器就都可以找到并访问根域DNS服务器了。
分配给根域DNS服务器的IP地址在全世界仅有13个,而且这些地址几乎不发生变化,因此将这些地址保存在所有的DNS服务器中也并不是一件难事。实际上,根域DNS服务器的相关信息已经包含在DNS服务器程序的配置文件中了,因此只要安装了DNS服务器程序,这些信息也就被自动配置好了。
DNS服务器会对已经查询过的域名以及对应的IP地址进行缓存
DNS服务器缓存查询流程:
这个缓存机制中有一点需要注意,那就是信息被缓存后,原本的注册信息可能会发生改变,这时缓存中的信息就有可能是不正确的。因此,DNS服务器中保存的信息都设置有一个有效期,当缓存中的信息超过有效期后,数据就会从缓存中删除。而且,在对查询进行响应时,DNS服务器也会告知客户端这一响应的结果是来自缓存中还是来自负责管理该域名的DNS服务器。
Socket创建,连接流程
收发数据的操作分为若干个阶段,可以大致总结为以下4个。(1)创建套接字(创建套接字阶段)(2)将管道连接到服务器端的套接字上(连接阶段)(3)收发数据(通信阶段)(4)断开管道并删除套接字(断开阶段)
前面这4个操作都是由操作系统中的协议栈来执行的,浏览器等应用程序并不会自己去做连接管道、放入数据这些工作,而是委托协议栈来代劳
此外,这些委托的操作都是通过调用Socket库中的程序组件来执行的,但这些数据通信用的程序组件其实仅仅充当了一个桥梁的角色,并不执行任何实质性的操作,应用程序的委托内容最终会被原原本本地传递给协议栈。
就是当调用connect时,协议栈就会执行连接操作。当连接成功后,协议栈会将对方的IP地址和端口号等信息保存在套接字中,这样我们就可以开始收发数据了。
下面一半是用IP协议控制网络包收发操作的部分。在互联网上传送数据时,数据会被切分成一个一个的网络包,而将网络包发送给通信对象的操作就是由IP来负责的。此外,IP中还包括ICMP协议和ARP协议。ICMP用于告知网络包传送过程中产生的错误以及各种控制消息,ARP用于根据IP地址查询相应的以太网MAC地址。
在协议栈内部有一块用于存放控制信息的内存空间,这里记录了用于控制通信操作的控制信息,例如通信对象的IP地址、端口号、通信操作的进行状态等。本来套接字就只是一个概念而已,并不存在实体,如果一定要赋予它一个实体,我们可以说这些控制信息就是套接字的实体,或者说存放控制信息的内存空间就是套接字的实体。
用命令查询已有的Socket:
套接字中记录了用于控制通信操作的各种控制信息,协议栈则需要根据这些信息判断下一步的行动,这就是套接字的作用。
创建套接字时,首先分配一个套接字所需的内存空间,然后向其中写入初始状态。
接下来,需要将表示这个套接字的描述符告知应用程序。描述符相当于用来区分协议栈中的多个套接字的号码牌
客户端向服务器传达开始通信的请求,也是连接操作的目的之一。
连接实际上是通信双方交换控制信息,在套接字中记录这些必要信息并准备数据收发的一连串操作,
客户端将IP地址和端口号告知服务器这样的过程就属于交换控制信息的一个具体的例子
此外,当执行数据收发操作时,我们还需要一块用来临时存放要收发的数据的内存空间,这块内存空间称为缓冲区,它也是在连接操作的过程中分配的。
第一类是客户端和服务器相互联络时交换的控制信息。这些信息不仅连接时需要,包括数据收发和断开连接操作在内,整个通信过程中都需要,这些内容在TCP协议的规格中进行了定义。
这些信息会被添加在客户端与服务器之间传递的网络包的开头,这里是tcp连接三次握手的开始
通信操作中使用的控制信息分为两类。(1)头部中记录的信息(2)套接字(协议栈中的内存空间)中记录的信息
这个过程是从应用程序调用Socket库的connect开始的。connect(, ,…)上面的调用提供了服务器的IP地址和端口号,这些信息会传递给协议栈中的TCP模块。然后,TCP模块会与该IP地址对应的对象,也就是与服务器的TCP模块交换控制信息
首先,客户端先创建一个包含表示开始数据收发操作的控制信息的头部。如表2.1所示,头部包含很多字段,这里要关注的重点是发送方和接收方的端口号。到这里,客户端(发送方)的套接字就准确找到了服务器(接收方)的套接字,也就是搞清楚了我应该连接哪个套接字。
然后,我们将头部中的控制位的SYN比特设置为1,大家可以认为它表示连接。此外还需要设置适当的序号和窗口大小,这一点我们会稍后详细讲解。连接操作的第一步是在TCP模块处创建表示连接控制信息的头部。
当TCP头部创建好之后,接下来TCP模块会将信息传递给IP模块并委托它进行发送
当找到对应的套接字之后,套接字中会写入相应的信息,并将状态改为正在连接
上述操作完成后,服务器的TCP模块会返回响应,这个过程和客户端一样,需要在TCP头部中设置发送方和接收方端口号以及SYN比特。此外,在返回响应时还需要将ACK控制位设为1,这表示已经接收到相应的网络包
网络包也会发生丢失,因此双方在通信时必须相互确认网络包是否已经送达,而设置ACK比特就是用来进行这一确认的。
接下来,服务器TCP模块会将TCP头部传递给IP模块,并委托IP模块向客户端返回响应。
网络包就会返回到客户端,通过IP模块到达TCP模块,并通过TCP头部的信息确认连接服务器的操作是否成功。如果SYN为1则表示连接成功,这时会向套接字中写入服务器的IP地址、端口号等信息,同时还会将状态改为连接完毕。
还剩下最后一个步骤。刚才服务器返回响应时将ACK比特设置为1,相应地,客户端也需要将ACK比特设置为1并发回服务器,告诉服务器刚才的响应包已经收到。
现在,套接字就已经进入随时可以收发数据的状态了
建立连接之后,协议栈的连接操作就结束了,也就是说connect已经执行完毕,控制流程被交回到应用程序。
整个硬件的图: