网络是怎样连接的--委托协议栈发送消息
Posted 捕获一只小肚皮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络是怎样连接的--委托协议栈发送消息相关的知识,希望对你有一定的参考价值。
文章目录
引言
此文所讲解的各种例子都是站在浏览器等客户端的角度,并未太多涉及服务器;
4.1 数据收发操作概览
知道了IP地址之后,就可以委托操作系统内部的协议栈向这个目标IP地址(要访问的Web服务器)发送消息了。要委托协议栈来发送的是数字信息,而收发数字信息这一操作不仅限于浏览器,对于各种使用网络的应用程序来说都是共通的。
下面就来一起探索这一操作的过程,和向DNS服务器查询IP地址的操作一样,这里也需要使用Socket库中的程序组件。不过,这个过程比起查询IP地址来说稍微复杂了一点,因为它是需要操作更多的Socket库中组件。发送数据是一系列操作相结合来实现的,如果不能理解这个操作的全貌,就无法理解其中每个操作的意义。
因此,我们先来介绍一下收发数据操作的整体思路。向操作系统内部的协议栈发出委托时,需要按照指定的顺序来调用Socket库中的程序组件,使用Socket库来收发数据的操作过程如下图。
简单来说,收发数据的两台计算机之间连接了一条数据管道,将数据从一端送入管道,数据就会到达管道的另一端然后被取出。数据可以从任何一端被送入管道,数据的流动是双向的。不过,这并不是说现实中真的有这么一条管道,只是为了帮助大家理解数据收发操作的全貌。
这里有个注意点,光从图上来看,这条管道好像一开始就有,实际上并不是这样,在进行收发数据操作之前,双方需要先建立起这条管道才行。建立管道的关键在于管道两端的数据出入口,这些出入口称为套接字。我们需要先创建套接字,然后再将套接字连接(一般是客户端连接服务端)起来形成管道,当双方的套接字连接起来之后,通信准备就完成了。接下来,只要将数据送入套接字就可以收发数据了;而想要结束通信就只需要断开管道(客户和服务端都可以主动断开);
综上所述,收发数据的操作分为若干个阶段,可以大致总结为以下4个。
- 创建套接字(创建套接字阶段)
- 将管道连接到服务器端的套接字上(连接阶段)
- 收发数据(通信阶段)
- 断开管道并删除套接字(断开阶段)
向web服务器发送消息过程和DNS服务器的类比
前面这4个操作都是由操作系统中的协议栈来执行的,浏览器等应用程序并不会自己去做连接管道、放入数据这些工作,而是委托协议栈来代劳
4.2 创建套接字
客户端创建套接字的操作非常简单,只要调用Socket库中的socket程序组件就可以了。和调用解析器一样,调用socket之后,控制流程会转移到socket内部并执行创建套接字的操作,完成之后控制流程又会被移交回应用程序。
套接字创建完成后,协议栈会返回一个描述符,应用程序会将收到的描述符存放在内存中。描述符是用来识别不同的套接字的,大家可以这样理解。我们现在只关注了浏览器访问Web服务器的过程,但实际上计算机中会同时进行多个数据的通信操作,比如可以打开两个浏览器窗口,同时访问两台Web服务器。这时,有两个数据收发操作在同时进行,也就需要创建两个不同的套接字。这说明,同一台计算机上可能同时存在多个套接字,在这样的情况下,我们就需要一种方法来识别出某个特定的套接字,这种方法就是描述符(其本质是一个数字编号),这样子协议栈就可以根据不同的描述符进行不同的数据操作;
4.3 连接管道
接下来,我们需要委托协议栈将客户端创建的套接字与服务器那边的套接字连接起来。应用程序通过调用Socket库中的名为connect的程序组件来完成这一操作。这里的要点是当调用connect时,需要指定描述符、服务器IP地址和端口号这3个参数。
第1个参数,即描述符,就是在创建套接字的时候由协议栈返回的那个描述符。connect会将应用程序指定的描述符告知协议栈,然后协议栈根据这个描述符来判断到底使用哪一个套接字去和服务器端的套接字进行连接,并执行连接的操作.
第2个参数,即服务器IP地址,就是通过DNS服务器查询得到的我们要访问的服务器的IP地址。在DNS服务器的部分已经讲过,在进行数据收发操作时,双方必须知道对方的IP地址并告知协议栈。这个参数就是那个IP地址了
第3个参数,即端口号,用来标识想要连接的服务器中的具体程序套接字;ip地址只是用来识别是哪个计算机,但并不能识别要和哪个程序进行数据交流
程序端口号并不用去查询,因为这是事先规定好了的,比如Web是80号端口,电子邮件是25号端口,根据规则,就可以连接到相应的服务器程序的套接字。
既然确定连接对象的套接字需要使用端口号,那么服务器也得知道客户端的套接字号码才行吧,这个问题是怎么解决的呢?
事情是这样的,首先,客户端在创建套接字时,协议栈会为这个套接字随便分配一个端口号。接下来,当协议栈执行连接操作时,会将这个随便分配的端口号通知给服务器。
总而言之,就是当调用connect时,协议栈就会执行连接操作。当连接成功后,协议栈会将对方的IP地址和端口号等信息保存在套接字中,这样我们就可以开始收发数据了。
4.4 开始通信
当套接字连接起来之后,剩下的事情就只要将数据送入套接字,数据就会被发送到对方的套接字中。
当然,应用程序无法直接控制套接字,因此还是要通过Socket库委托协议栈来完成这个操作。这个操作需要使用write这个程序组件,具体过程如下。首先,应用程序需要在内存中准备好要发送的数据。根据用户输入的网址生成的HTTP请求消息就是我们要发送的数据。接下来,当调用write时,需要指定描述符和发送数据,然后协议栈就会将数据发送到服务器。
由于套接字中已经保存了已连接的通信对象的相关信息,所以只要通过描述符指定套接字,就可以识别出通信对象,并向其发送数据。
接着,发送数据会通过网络到达我们要访问的服务器。然后服务器执行接收操作,解析收到的数据内容并执行相应的操作,向客户端返回响应消息。
当消息返回后,需要执行的是接收消息的操作。接收消息的操作是通过Socket库中的read程序组件委托协议栈来完成的.调用read时需要指定用于存放接收到的响应消息的内存地址,这一内存地址称为接收缓冲区。于是,当服务器返回响应消息时,read就会负责将接收到的响应消息存放到接收缓冲区中。由于接收缓冲区是一块位于应用程序内部的内存空间,因此当消息被存放到接收缓冲区中时,就相当于已经转交给了应用程序。
4.5 断开连接
当浏览器收到数据之后,收发数据的过程就结束了。接下来,我们需要调用Socket库的close程序组件进入断开阶段。最终,连接在套接字之间的管道会被断开,套接字本身也会被删除。
断开的过程如下。Web使用的HTTP协议规定,当Web服务器发送完响应消息之后,应该主动执行断开操作,因此Web服务器会首先调用close来断开连接,断开操作传达到客户端之后,客户端的套接字也便断开了(管道锻炼)。接下来,当浏览器调用read执行接收数据操作时,read会告知浏览器收发数据操作已结束,连接已经断开。浏览器得知后,也会调用close进入断开阶段。
这就是HTTP的工作过程。HTTP协议将html文档和图片都作为单独的对象来处理,每获取一次数据,就要执行一次连接、发送请求消息、接收响应消息、断开的过程。因此,如果一个网页中包含很多张图片,就必须重复进行很多次连接、收发数据、断开的操作。对于同一台服务器来说,重复连接和断开显然是效率很低的,因此后来人们又设计出了能够在一次连接中收发多个请求和响应的方法。在HTTP版本1.1中就可以使用这种方法,在这种情况下,当所有数据都请求完成后,浏览器会主动触发断开连接的操作。
=================================上一章============================
以上是关于网络是怎样连接的--委托协议栈发送消息的主要内容,如果未能解决你的问题,请参考以下文章