本文共 3435 字,大约阅读时间需要 11 分钟。
计算机网络分为应用层,运输层,网络层,数据链路层,物理层.
我们从客户端的应用层(也就是我们的日常应用)讲起,一层一层向下处理我们在应用程序里填写的数据,直到从客户端的物理层发送给服务器,再从服务器的物理层接受到这些数据开始,一层一层处理这些数据,再将数据转化成服务器应用程序能够理解的数据内容.人们在1.输入网址,或者2.在网站填写一些数据并点击发送按钮时,就会触发计算机网络的数据传输.
数据传输的过程在http协议这方面看,就是http协议根据用户请求向下发送一段请求消息,请求消息中包含(方法,URI). 方法主要有Get和Post两种1.网址由协议机制(http),Web服务器名域名(www.csdn.net),文件名(index.html)这几个部分组成.输入网址(我们点击超链接的过程也相当于在浏览器中输入了一段网址)后,http一般会形成GET方法和一个网页文件为URI的请求消息.
2.网页中的表单源码会记录使用哪些方法,和使用哪个程序来处理.在点击表单中相应的按钮,就会触发向服务器发送请求消息的过程.请求消息的格式:
这个请求消息实际上还需要客户端其他几层的处理,但是再经过层层处理达到服务器的应用层时,服务器程序所看到的也是大致一模一样的请求消息内容.
以上的内容就是浏览器根据http协议生成的报文的过程了.
浏览器生成了报文以后,需要依靠操作系统将报文发送给服务器端,就像系统调用一样.那么这个委托操作之前呢,我们还必须要将url的服务器域名转换成它的IP地址.因为操作系统是不认识服务器域名的.所以我们需要先想办法找到服务器的IP地址.(服务器的IP地址就像是一个门牌号一样,全世界的服务器的IP地址都是不同的.)
下面先简单介绍一下ip地址,其实这个东西我们在计算机中已经见过很多了吧.
我们在使用电脑时见到的这个32比特,按8比特为一组的分为4组的,分别用十进制表示然后再用圆点分割的就是所谓的IP地址了.实际上/后面的就是IP地址的子网掩码,子网掩码的作用就是用来表示IP地址哪一部分是网络号哪一部分是主机号
那么浏览器是如何将我们输入的网址制作成ip传给操作系统的呢?其实依靠的就是DNS(域名解析系统).浏览器会向DNS服务器发送一段查询消息,DNS服务器的响应消息中就有网址对应的ip地址.
那么具体是怎么做的呢?浏览器等这些会联网的应用程序中会使用到一个叫做DNS解析器的程序.有C语言编程基础的,就会明白,编程时我们会调用C库里的程序,比如printf之类的,这里的DNS解析器也是相当于printf一样的一个函数.
客户端通过将查询信息发送给最近的DNS服务器,最近的DNS服务器又再访问根域DNS服务器,根域再一层一层往下,找到最小域的DNS服务器,这个DNS服务器中就存储了我们所要查询的Web服务器的ip地址了.
通过DNS服务器获得了Web服务器的ip地址之后,那我们就可以把修改好的报文发给协议栈(也就是tcp/ip传输层和网络层)。那么浏览器是如何把修改好的报文下发给协议栈的呢?其实我们这里的发送说法是逻辑上的。实际上,就像我们程序设计中的结构一样,我们设置了底层数据库增删查改的基础函数,然后再在业务逻辑层上设计处理数据库增删查改产生的包装好的数据的处理函数。那么这里的协议栈就像业务逻辑层一样,而业务逻辑层处理数据库访问层中产生的数据,像是协议栈处理应用层产生的报文一样。只是我们平常程序设计的最终目的是给普通人能够直接使用,而现在的目的是将应用程序产生的数据可以在网路上传输。所以感觉上像是反了一样。还有一点不同的是,我们的业务逻辑层是通过调用数据库访问层来主动访问下层的,但是协议栈是应用程序调用Socket库中库函数,将数据作为参数传输给协议栈,所以协议栈是被动获取数据的。
了解计算机系统的应该明白,使用Socket库(也就是C库中的一个库),跟系统调用还是有区别的。不如说,C库的库函数有作系统调用的操作。这么看来,协议栈既然是属于系统的功能,而应用程序只是通过Socket库委托协议栈工作,那么Socket库也可以算在应用层的范畴里了,我们同样可以绕过Socket库直接进行系统调用协议栈,毕竟网络出现还是要比C语言要早的。但是我想,java这些语言的底层既然是通过C来做的,那么它们访问网络恐怕最终的最终还是得由Socket库来实现的吧。
好了,这里总结一下,Web应用程序中都做了什么事情呢?当然这里是以TCP形式的连接为例。UDP是不需要连接的。
首先Web应用程序会通过一Socket库的gethostbyname()函数来从DNS服务器上获取ip,然后就可以制作成最终的报文。
制作成报文之后,使用Socket库中的socket()函数,建立网络连接的端口(也就是套接字,有点玄,但是会在传输层中解释什么叫套接字,个人认为这个端口应该是属于传输层的范畴,应用程序所看到的就是一个网络连接的描述符)。 应用程序有了自己的端口,那么就可以通过Socket库中connect()函数连接服务器上的端口了。 连接完成之后就按照需求使用Socket库的Write(),Read()函数,发送请求的报文和读取响应的报文了。但是我们会注意到Write和Read并没有将什么数据返回给应用程序。其实底层中,Write和Read只是将数据从协议栈中拿出来,放到应用程序的缓冲区中,那么处理这块缓冲区的数据的方法就很多了。计算机网络的功能就到此为之。 最后就是调用Socket库中的Close()函数,来删除本机的端口。 如图所示转载地址:http://wtbr.baihongyu.com/