探索浏览器(二)
- 接上一篇的内容,继续这个探索的编写,其实就是自己根据书本目录写出了自己的理解
3、全世界的DNS服务器大接力
- 1、DNS的基本工作
也就是说,我们在前面已经讲过了解析器将消息发送到DNS服务器时,DNS和解析器会发生怎样的一种交互呢?我想用下面的图会更能了解这样的过程
- 如上所示:我们通过客户端的操作系统协议栈,
- 1、将我们查询域名解析的信息发送给服务器,这些查询的消息,包括我们的域名、class、记录类型等
- 2、服务器在自身通过查询记录的域名信息,匹配到了之后发送给客户端,当然查询的过程可不是那么简单,你想想,它能存下全世界的IP信息吗?当然不可能,所以他需要其他的服务器帮忙
- 3、将查到后的响应消息,返回这些消息
上面的域名信息就不多说了,那么class信息是我们的信息类型,比如class=IN(因为没有其它网络,只有互联网,所以永远都是IN)。而其记录类型就是我们的消息是啥?比如记录类型=A(A是address,网址的简称)。还有MX也就是Mail eXchange(邮件交换)等类型。
- 2、域名的层次结构
就像上次所说,我们不可能只用一台DNS服务器存下全世界的域名,所以会有很多服务器的协同合作来完成这个任务,那么这个时候,他就会出现服务器的分布层次问题了,相当于一个公司的管理层层次分明的分布,才能起到最大的作用。
诸如:我们的www.dhis.room.com 这个域名如果按照公司的的组织结构来讲,就是com集团的room部门dhis科的www,这样就形成了一个一个的域。
- 总的来说就是,比如我们给中国分配了cn,然后下一个域是hunan,然后是某个公司的域csu,然后就是www服务器名称,是不是会更懂一点。
https://www.csu.edu.cn
这个就是一个典型的例子,cn代表中国的域,edu代表教育行业的域,csu是中南大学,www是服务器名称,这样我们在寻找DNS服务器时,就不会出现错乱的情况了。
- 3、 寻找相应的DNS来获取IP地址
如果我们在注册域名时,不按照规律保存,而是胡乱存放,那么这些域名的IP会在全世界各地分布,那么寻找起来就很困难,那么我们就可以用分层注册的方式
- lab.csu.edu.cn这个域名是中南大学的图书馆,它注册时,需要将该域的服务器的域名存放在上域的DNS服务器中
- 也就是说保存在csu.edu.cn的DNS服务器中,而这个域的服务器IP地址又需要存放在上一个域的DNS服务器中
- 也就是说存放在edu.cn的DNS服务器中,同样的这个域名的IP会存放在上一个域cn的服务器中,这样便于上一级查询下一级。也可以层层向上查询。
那么我们再想一想,每个国家的后缀都是不同的,比如中国是cn,而日本是jp这样的后缀,他们是如何跳转,找到其它国家的DNS服务器的IP的呢?
这里就要提到一个根域的概念了,其实根域是真实存在的,在我们的cn后面正常情况下会加一个符号“.”,这个点和域名前面的点一样,只是是根域的代表,它存放全世界的国家域名服务器IP,而根服务器的IP地址只有13个,但是服务器的数量远不止此。
- 当然了,我们还应该知道一个概念,那就是,我们在配置我们的DNS服务器时,根服务器的IP一般都会自动配置好,接入上一层域是配置服务器必不可少的一段过程。最终这些配置都会作为以一个配置文件存在服务器中。
- 4、通过缓存加快访问响应
这个理解起来就更容易了,比如第一次我们在浏览器中输入百度的域名,经过前面一系列的解析,发送和查询,最终找到了我们的IP地址,并且访问成功。
————————————————————————
但是第二次再次访问百度时,就会根据上次存放的IP地址,直接访问,这样就会省去很多的时间,毕竟我们的客户端不会访问太多的网址,所以这样的一套缓存作用很明显。
4 委托协议栈发送消息
- 1、数据的收发操作
向操作系统内部的协议栈发出委托时,需要按照指定的顺序来调用Socket库中的程序组件
- 也就是说我们在向DNS服务器发送查询IP地址时的信息,也许只有一行程序代码就可以了,Socket库中的gethostname来获取IP,但是我们向web服务器发送消息时,可不止这样的一个程序来发出我们的信息,所以就需要Socket库中的很多程序组件来组合发送消息,如下所示:
- 其实不管怎么说,很简单的理解就是,我们在传送数据时,是先简历连接后,才开始传输数据的,这样的过程大致可以分为如下:
1、服务器创建一个套接字,然后处于接收状态,这个时候客户端就可以创建套接字了(创建阶段)
2、客户端的套接字将管道连接到服务器的套接字上(连接阶段)
3、开始传输数据(通信阶段)
4、任意一方断开连接,删除管道,停止通信(断开阶段)
- 这里我们参考一下我编写的UDP通信实例:
//1.创建连接
Socket socket = new Socket(InetAddress.getByName("192.168.43.67"),8088);
//2.创建输出流
OutputStream os = socket.getOutputStream();
//3.读取文件
FileInputStream fi = new FileInputStream(new File("1.jpg"));
//4.写文件
byte[] buffer = new byte[1024];
int len;
while((len=fi.read(buffer))!=-1){
os.write(buffer,0,len);
}
//关闭socket以免服务器一直接受
socket.shutdownOutput();
- 上面是我们的客户端一部分代码,可以看到我们首先创建了一个socket,通过这个套接字的创建,然后就是创建输出流,然后写文件之类的,最后关闭服务器。
//1.创建服务
ServerSocket serverSocket = new ServerSocket(8088);
//2.监听客服端的连接
Socket socket = serverSocket.accept();
//3.获取输入流
InputStream is = socket.getInputStream();
//4.文件输出
FileOutputStream fio = new FileOutputStream(new File("receive.jpg"));
- 上面是服务器端,它创建了一个服务器套接字后开始接受,这个端口的连接消息,成功后开始接受消息。
- 2、创建套接字的过程
这个过程总结来说,就是我们的客户端调用Socket库中的程序就可以了,这就是我们表面能看到的最直接的东西,后面会有更复杂的原理不作过多解释,后面的章节会提到。
- 上面的简单介绍,其实就已经把整个创建过程描述了,但是这个过程还会返回一个描述符给程序,这个描述符就是用来区分我们的套接字属于不同的程序的标记。
- 想一想,假如我们打开了多个浏览器页面,分别搜索了不同的服务器,那么这些不同的服务器在同时没有混乱的将搜索页面显示。
- 说明第一个:它是可以创建多个套接字的
- 第二个:它有可以区分的机制,从而来区分不同的程序请求的不同套接字
-3、连接阶段
这个阶段就是我们通过管道将客户端和服务器端的套接字相互连接,这里连接通过Socket库中的connect程序来连接
——————————————————————
调用该程序时,需要传入三个参数:描述符、服务器IP地址、端口
- 我们就来一一介绍这三个参数的不同含义。
- 描述符:这个是我们的协议栈在发送消息后,会得到一个反馈,这个反馈是我们客户端去连接服务器端时的套接字区分号,也就是说这个决定我们在连接服务器端时是否能找到客户端的套接字。
- 服务器IP地址:这个就不过多解释了,这是我们千方百计才得到的信息,现在就用上了
- 端口:端口,这个是我们用来确定某台具体计算机上的某个具体套接字的。比如80是web端口号,25是电子邮件端口号。
- 4、传递消息
这个时候是通过Socket中的write程序来实现的,接收消息是通过read来实现
- 这个过程其实就水到渠成了,管道都已经铺好,只需要往里面塞东西,然后读出来就行了
- 5、断开连接
最终传输完成后,断开连接必不可少,这个时候,就是任意一方提出断开连接就行
- 在这里会有四次挥手的操作,具体内容会在后面解释,现在我们只需要了解有这个过程
- 它通过Socket库中的close来实现
个人总结
- 其实也没什么总结的,除了困就是困,写完睡觉,哎呦,明天还要考试!加油吧