《网络是怎样连接的》读书笔记

第一章: 浏览器生成信息

首先浏览器从拿到输入的地址开始,先要解析uri,生成http消息,然后委托操作系统发送消息,需要提供ip地址,所有要根据域名查询ip需要向DNS服务器发送查询,通过gethostbyname解析器(存在操作系统的socket库中),需要向DNS服务器发送包含域名、Class、记录类型去匹配查询记录表里面对应的ip地址,得到ip地址后,应用程序(浏览器)委托操作系统内部的协议栈向目标IP发送消息,这个过程需要按照指定的顺序来用socket库中的程序组件,服务端和客户端都会创建套接字(也就是数据出入口),套接字创建之后,协议栈会返回一个描述符(因为同一台计算机可能同时有多个数据收发的操作,可能同时存在多个套接字,所以这个描述符其实就是拿来标识计算机内部,他是哪一个套接字),将管道连接到服务器的套接字上,连接需要提供ip和端口号,(端口号是让通信方能够识别出来这个套接字),进行收发数据,服务器返回响应消息时,客户端中的read(socket里面的程序组件)会将消息存放到接收缓冲区,最后断开管道删除套接字,整个过程协议栈去执行的。

第二章:用电信号传输TCP/IP数据

​ 在协议栈的内部有用于存放控制信息的内部空间(可以理解为套接字的实体,在本机在命令行输入netstat—ano可以查看本机创建的套接字),控制信息分为两类:一是头部记录的消息(主要是发送方和接收方端口号),二是套接字中记录的消息(用来控制协议栈操作的消息)。创建套接字后,应用程序调用connect连接,将头部的控制位SYN(确认字符,表示已正确接收设1)比特设置为1,设置序号初始值(这个是告诉接收方,自己发送的是从第几个字节开始的部分)、窗口大小(接收的消息,不会马上给应用程序,会有个数据接收缓冲区,窗口大小就是缓冲区能够接受的最大数据量),将包含序号和窗口大小的包发给接受方。接收方会返回表示收到的包ACK号,同时将窗口,SYN设为1以及序号初始值给发送方(窗口大小的更新和序号以及ACK是双向进行的)。确认连接之后进行收发操作,发送方发送含有序号和数据的包,接收方响应ACK号和窗口大小。

​ 而这个网络包传到服务器是由tcp模块委托IP模块打包发送/接受的,网络包分为头部和数据两部分,头部的Tcp头部的是tcp模块加的,然后交给IP模块,而ip模块负责添加mac头部和ip头部,封装好的包交给网络硬件(很多,统称网卡了)。ip地址实际上不是分配给计算机的,是给网卡的所有当一台计算机存在多张网卡,就有多个ip地址,所以发送方的IP头部包括了接收方的ip地址还有自己的IP地址(这样才知道这个包是从这台计算机的哪一个网卡发出来的)。判断交给哪个网卡是根据ip地址和路由器表进行比较来选择的。还有需要协议号,就是这个包是来自tcp还是udp模块的,而MAC头部是在以太网将包发送给下一个转发设备(或者接收方)的依据。传输网络包时,路由器根据目标地址判断下一个路由器,集线器是在子网中将包传给下一个路由。所以在传的过程中,ip头部是一直不变的,而mac头部在路由器转发是将地址改写为下一个路由的mac地址。MAC地址也是物理地址,是生产商在生产时写进ROM只读存储器的,唯一的地址。在传输过程中可以根据查路由表知道发送给谁了(IP地址),但是并不知道对方MAC地址,要提供ARP(根据IP地址获取MAC地址)查询目标的MAC地址。

​ ARP的原理是利用广播,对所有设备查询这个ip地址的mac地址。ARP有缓冲区,这个缓存区几分钟更新一次,因为每次都查,会增加很多ARP,有缓存的话,会先查缓存,几分钟更新一次,确保数据有效(刚好更新的时候查,这就会通信异常,可以手动删除过时的条目)。到目前为止,整个打包过程是有ip模块完成,网卡就只管发送,这样网卡可以发送各种类型的包,因为他不需要管这是ip包,还是什么。再由网卡将这些包(一连串0或1的二进制流)转换为电信号或者光信号(根据0/1控制对应的电压和电流)发送出去给集线器、路由器等转发设备,由转发设备一步步送到接收方。

第三章:从网线到网络设备

​ 网卡中将包转换为电信号的是PHY(MAU)模块(一个从正负两个信号端子输出信号的电路),然后信号通过RJ-45接口进入双绞线,流入网线到达集线器接口(这个过程就是传输电信号而已)。在网线传输过程中网线越长,信号衰减就越严重,信号会失真。以太网中信号波形是方形的,损失能量会让信号拐角变圆,会出现对0/1的误判,产生通信错误。局域网网线使用双绞线(两根±信号线为一组缠绕在一起的网线),是为了抑制噪声影响。其中螺旋形是为了抑制网线之外设备的电磁波,±信号线是抑制内部噪声(串扰)的影响。

​ 网络包通过集线器:集线器要将发送线路和接受线路连接,所以集线器中的PHY(MAU)模块与接口之间采用交叉接线(MDI-X)。信号到达PHV(MAU)模块后,进入中继电路(将信号广播到集线器所有端口),信号从所有接口流出,到达连接到集线器的所有设备,这些设备通过MAC头部中接收方的MAC地址判断是不是发给自己的,是就接受,不是就忽略,这样网络包就到指定MAC地址接收方了。

​ 网络包通过交换机:信号到网线接口(MDI-X),和集线器一样是PHY(MAU)模块(会转换为通用格式)接收,然后传给MAC模块(转换为数字信息),通过包末尾的FCS校验错误,没问题(错误就丢)就放到缓冲区。交换机端口的MAC模块不具有MAC地址的原因就是因为交换机直接收了所有包(不需要核对接收方MAC地址看是不是发给自己的了,因为都收)放到缓冲区。接下来查询这个包的接收方MAC地址在MAC地址表(交换机内部的MAC地址和网线端口对应表)有没有记录,根据这些信息判断把包转发到哪里。交换机的信号线排列成网格状,交叉点有控制开关,切换开关可以改变信号流向,独立工作,所以只要路径不重复,可以同时传输多路信号。将信号发送到网线中和网卡发送信号是一样的,根据以太网规则检测其他设备发送信号(碰撞检测机制),避免信号碰撞,导致发送阻塞。如果接收方MAC地址是广播地址,会将包发送给除了源端口之外所有设备。全双工模式是交换机特有的模式,可以同时进行发送和接受操作,集线器没有这种。前面刚说的需要检测的是半双工模式。因为有两种模式,刚开始需要手动切换,太麻烦,后来就有了自动切换工作模式(自动协商)的功能,还能检测对方的传输速率。原理:在以太网中,没有数据传输时,填充连接脉冲的脉冲信号,使得网络中一直都有信号流过,从而检测对方是否正常工作。后来设计了特定排序的脉冲信号可以告诉对方自己的状态,自动协商功能接受利用这种信号,将自己的工作模式和传输速率告诉对方。而且交换机只将包转发到特定的MAC地址设备连接端口,其他端口都是空闲的,这些端口可以传输其他包,所以交换机可以同时转发多个包。而集线器要广播到所有端口,同时输入多个信号会信号碰撞。

​ 网络包通过路由器:首先这个过程就是会路由器转发到下一个路由器。工作原理和交换机类似,不过路由器是基于IP设计的,而交换机是基于以太网设计的。路由器包括转发模块和端口模块两部分,转发模块负责判断包转发到哪里,端口模块负责包的收发操作,相当于IP模块和网卡之间的关系,一个负责告诉目的地,另一个发和收。因为端口模块以实际的发送方和接收方收发网络包,所有路由器端口具有MAC地址,端口还具有ip地址,和网卡一样。路由器的各个端口都有MAC地址和IPd地址。转发包的时候,路由器端口会接受发给之间的包在查询转发目标,然后从相应的端口(以太网端口、无线局域网、通信线路…),作为发送方发送出去。路由器还有个分片功能拆分网络包(拆TCP头部及其后面数据部分)。区别:交换机就只是就进来的包转发,不会成为接收方和发送方的。还有交换机是通过MAC头部接收方的MAC地址判断转发对象,路由器是根据IP头部的IP地址判断,路由器会忽略主机号,只匹配网络号(网络号和主机号的比特数的值就是子网掩码)。路由器接受包和网卡很像,路由器接受之后会丢弃包开头的MAC头部,然后自己查表(下一个路由器的mac),也会使用ARP查询下一个转发目标的MAC地址,加上MAC头部(准确的说是将ip包装进以太网数据部分,委托以太网传输)。总结:IP(路由器)负责将包送到通信对象的整体过程,而其中将包传输给下一个路由器的过程是由以太网(交换机:基于以太网)来负责。

​ 路由器还有地址转换功能,这里了解了公网地址和私有地址。公网地址是唯一性的,出现在互联网,像门牌号,到哪里都可以识别;私有地址只存在局域网中,互联网中不能出现,类似于酒店房间号,基本哪个酒店都是这样编号,只告诉别人房间号,谁都不知道你在哪里(哪个具体酒店)。公司内网分为两个部分:一部分是对互联网开发的服务器,对其分配公有地址,另一部分是公司内部设备,分配私有地址,不能和互联网直接收发网络包,而是通过地址转换机制。地址转换机制的原理是在转发网络包时对IP头部中的IP地址和端口号进行改写,将私有改公有(地址转换器的互联网接入端口的地址),端口号也要改写,然后作为一组相对应的记录保存在地址转换设备内部的一张表里面。还要改端口,而不是直接改IP为公有地址,可以一个公有地址对应几万个(不同的端口,及内网中不同的终端)私有地址,提高公有地址利用率。从互联网访问公司内网,对应表没记录不能正常发(防止非法入侵),要手动添加表记录。

第四章:通过接入网进入互联网内部

​ 今天是从互联网接入网进入互联网内部到达服务器pop端的过程。主要了解了两种接入网:一种是ADSL(不对称数字用户线)接入网,另一种是光纤接入网(FTTH:光纤到户)。接入网就是用来连接网络运营商的线路。
​ 互联网接入路由器会在网络包前面加上MAC头部、PPPoE头部、PPP(点到点协议)头部总共3种头部,然后发送给ADSL Modem(PPPoE方式下),ADSL Modem会把把拆分成很多小格子,每一个小格子叫信元,用于ATM(异步传输)的通信技术,并转换(专业一点叫调制,ADSL Modem采用一种圆滑波形/正弦波对信号进行合成来表示0/1的技术,有点复杂,还和振幅相位有关,物理知识不具体说了)成电信号发送给分离器。ADSL通过多个波来提高速率,因为波量不同,所以上行方向(用户到互联网)和下行方向(互联网到用户)的传输速率不同,而且噪声和衰减等影响线路质量的因素在每个线路上不同,会随着时间变化,所以ADSL还会持续检查线路质量,当Modem通电后,会发送测试信号,根据信号接收情况判断使用的频段数量和每个判断的比特数,这个过程叫做训练(握手)。信号到达分离器之后,ADSL信号会和电话的语音信号混合进来一起从电话线传输出去,分离器实际上没干啥。分离器将电话和ADSL信号进行分离的操作是在信号从电话线流入的时候。从分离器出来,会通过室内电话线,然后得到大楼的IDF(中间配线盘)和MDF(总配线盘),到达安保器,接下来进入电话线到达电话局,经过配线盘和分离器到达DSLAM(数字用户线接入复用设备,一种电话局用的多路ADSL Modem),在这里电信号被还原为数据信息(信元),然后到达BAS(宽带接入服务器,确实是个路由来的)包转发设备,BAS将ATM信元还原成网络包,会取出PPP头部以及后面的数据,MAC头部和PPPoE头部就被他给丢弃(这两头部作用是将把送到BAS接口,所以现在没用了,就和路由器丢MAC头部一个道理),然后加上隧道专用头部,网络包到隧道专用路由器之后,这个隧道头部也会被丢,取ip包转发到互联网内部。
​ 另一种基于光纤的接入网(FTTH),(光纤的通信原理:数字信息转电信号,利用电压的变化发光,光信号在光纤传导到接收端,利用光敏元件根据亮度产生不同电压,再电信号转数字信息)FTTH主要使用单模光纤(省略单模和多模光纤原理,大概看了就是和发射角有关,又是物理知识来着)。用光纤代替ADSL将用户端接入路由器和运营商的BAS连接起来的接入方式就是FTTH,形态大致两种:一种是用一根光纤直接从用户端连接到最近的电话局,使用光纤接收器,另一种是在用户附近的电线杆上安装一个分光器,使用一个ONU设备(终端盒)。光纤接收器和ONU一样可以将电信号转换为光信号,并通过光纤到达BAS前面的多路光纤接发器和OLT(光线路终端),最后被还原为电信号到达BAS。
​ ADSL和FTTH接入网都需要先输入用户名和密码,登录之后才能访问互联网,而BAS就是登录操作的窗口。ADSL和FTTH接入网也需要为计算机分配公有地址才能上网。BAS使用PPPoE方式实现用户认证和配置下发功能,PPPoE是将PPP消息装入以太网包进行传输的方式,除了PPPoE,还有PPPoA、DHCP。BAS通过隧道将网络包发送给运营商,一种实现方式是TCP连接,建立TCP连接,连接两端的套接字当作路由器端口,基于隧道规则向隧道中放入或取出网络包。另一种基于封装的隧道实现方式,将包装入另一个包传输到隧道另一端,就是将包原封不动的搬运到另一端。还有找到BAS的方式,根据PPPoE发现机制查询BAS的MAC地址,和ARP一样基于广播来实现。
​ 网络包通过接入网之后到达运营商POP路由器,NOC(网络运行中心)是运营商的核心设备,从POP传来的网络包都集中到这里,并被转发到离目的地更近的POP,或者转发到其他运营商。互联网内部使用BGP(边界网关协议)机制在运营商之间交换路由信息,每个运营商和其他多个运营商是相互连接的,如果一个运营商走不下去,可以去另一个运营商。通过IX(互联网交换中心),就可以和整个互联网中的所有运营商交换数据了。IX核心是具有大量高速以太网端口的二层交换机,IX(也叫终端交换机)以及从点扩展到线甚至面。运营商之间可以直接连接,也可以通过IX连接,通过POP接入服务器端网络。

第五章:服务器端的局域网中有什么玄机

​ 防火墙其实就是有包过滤(还有其他方式实现防火墙目的的)的路由器,可以根据网络包的起点和终点来判断是否允许其通过,类似海关,只允许发往指定服务器的指定应用程序的网络包通过,屏蔽其他不允许通过的包,这样从互联网传来的包就不会无节制的进入服务器了。包过滤的规则,通过接收方和发送方IP地址判断起点和终点,通过端口号限定应用程序,通过控制位判断连接方向,(还可以根据其他条件)按照规则过滤TCP连接的第一个包。但是使用UDP协议的应用程序(比如对DNS服务器的访问)无法将允许和阻止的访问完成区分开,因为它和TCP不同,没用连接操作,不能通过控制位来判断访问方向。这种情况只能择其一,要么允许所有包通过,要么阻止。但是如果是使用包过滤之外其他方式的防火墙,有时可以判断udp应用程序的访问方向。防火墙除了包过滤,还有应用层网关、电路层网关等可以实现允许特定包发往特定服务器中特定应用程序的功能。包过滤方式的防火墙不仅可以允许和阻止网络包的通过,还有地址转换的功能,当使用地址转换时,默认状态下是无法从互联网访问公司内网的,所以不需要再设置包过滤规则来阻止从互联网访问公司内网。防火墙不能筛选出含有特定数据风险的包,只有检查包内容才能识别这种风险。这个问题的根源在于服务器端程序的bug,第一种方法是修复bug防止宕机(也应该也是服务器需要持续维护、关注安全漏洞信息并更新软件版本的原因之一吧),另一种方法就是在防火墙之外部署检查包内容并阻止有害包的设备或软件(有时会作为防火墙的附件提供)。

​ 性能不足的时候需要负载均衡(我记得在208的时候,师兄和我讲过这个的)。当服务器的访问量上升的时候,增加服务器线路的带宽是有效的,但是高速线路会传输大量网络包,就导致服务器的性能跟不上,尤其是通过CGI(通用网关接口,在物理上是一段应用程序,运行在服务器,提供同客户端HTML页面的接口,只要是提供html服务器端程序都可以叫CGI。)等应用程序动态生成数据的情况下,对服务器的CPU负担更重,服务器的性能问题也会更明显。可以使用多台服务器来分担负载的方法,这种架构统称为分布式架构。实现负载分担的方法,最简单的一种就是采用多台web服务器,减少每台服务器的访问量。具体做法,一种是通过DNS服务器来分配,在DNS服务器中填写多个名称相同的记录,每次查询时DNS服务器都按顺序(轮询)返回不同的IP地址,通过这种方式将访问平均分配给所有的服务器。这种方式的缺点是,当其中一台服务器宕机,可能依然返回这台服务器IP(如果浏览器在访问DNS服务器返回的第一个IP地址失败,能够继续尝试第二个IP地址,就可以回避这个问题,现在有的浏览器已经具备这样的功能了),轮询分配还可能出现的问题是通过CGI等方式动态生成页面情况下,如果这期间访问的服务器发生变化,这个操作就无法继续。(比如购物网站,第一个页面输入收货人信息地址,第二个页面输入付款方式)为了避免这种情况,可以使用负载均衡器。原理:首先用负载均衡器的IP地址代替web服务器的实际地址注册到DNS服务器上面。客户端会认为负载均衡器就是一台web服务器,向其发送请求,然后让负载均衡器去判断请求转发给哪台服务器。如果操作没用跨多个页面(CGI),可以根据服务器的负载情况来判断。负载均衡器可以定期采集web服务器的cpu、内存使用率这些数据判断负载状况,也可以向web服务器发送测试包,根据响应所需时间来判断负载状况。还有一种方法是不去查询服务器的负载,而是事先设置服务器的性能指数,按比例来分配。当操作跨多个页面,不考虑服务器的负载,必须将请求发送到同一台web服务器。所以这里怎么判断一个操作是不是跨多个页面?Http的基本工作方式是发送请求消息之前先建立TCP连接,当服务器发送响应消息后断开连接,下次访问web服务器时再重新建立TCP连接。所以在服务器看来,每一次的HTTP访问都是相互独立的,无法判断是否和之前的请求相关。判断请求之间的相关性,可以在发送表单数据时在里面加上用来表示关联的信息,或者是对HTTP规格进行扩展,在HTTP头部字段加上用来判断相关性的信息,这种信息就是cookie。(突然想起了之前学习Java web的时候,每次通过登录页面通过转发访问到首页信息,但是直接在地址栏输入首页的地址,一样可以访问到首页,登录页面根本不起作用,当时就是在用户登录后通过设置cookie保存在请求协议中,判断对首页以及其他页面是属于同一个用户(同一个cookie)的一系列操作,这样无法跳过登录去访问首页)原来cookie的设置对于服务器来说还判断了操作的相关性,将一系列相关的请求发送到web服务器,不相关的发送到负载较低的服务器。

​ 除了使用多台功能相同的web服务器分担负载之外,还可以将整个系统按功能分成不同的服务器,如web服务器、数据库服务器。缓存服务器就是一种按照功能来分担负载的方法。缓存服务器是一台通过代理机制对数据进行缓存的服务器,代理介于web服务器和客户端之间,对web服务器访问进行中转。可以将服务器返回的数据保存在磁盘中,并代替web服务器将磁盘中的数据返回给客户端,这种保存的数据称为缓存。缓存的数据不是永久可以的,服务器会更新数据,而且CGI程序产生的页面数据每次都不同,这些数据也无法缓存。缓存服务器的工作过程:首先,代替web服务器被注册到DNS服务器,然后客户端向缓存服务器发送消息,接收操作和web服务器一样,接下来,缓存服务器检查请求数据是否在缓存中,假设不存在,会在HTTP头部字段添加Via字段,表示这个消息已经经过缓存服务器转发,然后将消息转发给web服务器。需要根据请求消息的内容来判断应该转发给哪台服务器,可以根据请求消息的URI中的目录名来实现,转发的过程中,缓存服务器会以客户端的身份向目标web服务器发送请求消息,然后缓存服务器会在web服务器响应消息中加上Via头部字段,表示这个消息经过缓存服务器中转,然后以web服务器的身份向客户端发送响应消息,同时将响应消息保存在缓存中,并记录保存的时间。命中缓存(就是用户又访问这个已经访问过的数据)的情况:接收客户端请求消息和检查缓存和前面一样,缓存服务器会添加一个If-Modified-Since头部字段,并将请求转发给web服务器,询问web服务器用户请求的数据是否发生变化,然后web服务器会根据If-Modified-Since的值与服务器上页面数据最后更新时间进行比较,如果在指定时间内数据没有变化,就会返回表示没有变化的响应信息:304 Not Modified,缓存服务器就知道web服务器上数据和本地缓存中一样,于是将缓存的数据返回给客户端,返回的响应信息就和没有命中缓存的情况一样。当web服务器上数据有变化时,过程和没有命中缓存的情况一样。

​ 最开始的代理是部署在客户端的缓存服务器,称为正向代理。部署在服务器一侧的就是反向代理。正向代理刚出现的时候,目的之一是缓存,还有一个目的就是实现防火墙,由于代理在转发的过程中可以查看请求的内容,所以可以根据内容判断是否允许访问。当浏览器设置了正向代理IP地址,浏览器会忽略网络栏的内容,将所有的请求发送给正向代理,没有设置时,会从网址提取出web服务器域名后面的文件名和目录,然后作为请求的URI进行发送。使用正向代理可以根据完整的网址来转发,不需要像服务器的缓存服务器一样事先设置好转发的web服务器。还有一种透明代理,根据请求消息的包头部(IP头部包含接收方的IP地址),就知道用户要访问哪台服务器了。正常情况下,请求信息是从浏览器直接发送到服务器,不会到透明代理器,所以透明代理是在消息经过时进行拦截,所以一般在连接互联网的接入口(只有一条路可以走)放置透明代理,因为用户察觉不到它的存在,所以更倾向于叫缓存。(也可以采用网络中的某些地方将web访问包筛选出来并转发给透明代理器)。

​ 两种部署缓存服务器的方式都有利弊,还有一种能够集合两者优点的方式,就是Web服务器运营商和网络运营商签约,将可以自己控制的缓存服务器放在客户端的运营商处。要实现这种方式,必须在所有(或者主要)运营商的POP中都部署缓存服务器才行,还有一个现实的问题,就是web服务器的运营商自己和网络运营商签约并部署缓存服务器,费用和精力都是吃不消的。所以一些专门从事相关服务饿厂商出现了,他们来部署缓存服务器,并租借给web服务器运营商,这种称为CDS/CDN(内容分发服务),提供这种服务的厂商叫做CDSP(内容分发服务运营商),他们会和主要的供应商签约,并部署很多缓存服务器。CDSP会和web服务器运营商签约,使得CDSP的缓存服务器配合web服务器工作。只要web服务器和缓存服务器建立关联,当客户端访问web服务器时,实际上就是访问CDSP的缓存服务器。缓存服务器可以缓存多个网站的数据,因此CDSP缓存服务器就可以提供给多个web服务器的运营商共享,这样,每个网络运营商的平均成本就降低了,和运营商之间的签约工作也是CDSP统一负责,网络运营商也节省了精力。
​ 互联网中有很多缓存服务器,怎么样找到丽客户端最近的一台。第一种方法是像负载均衡一样用DNS服务器来分配访问,但是如果一个域名对应多个IP地址,这时不能使用轮询的方式返回所有IP地址,这种方法不考虑客户端与缓存服务器的远近,可能会返回较远的缓存服务器。要判断客户端和缓存服务器的距离,一种方法是,需要事先从缓存服务器部署地点的路由器收集路由信息,并将获取到的路由表集中到DNS服务器上,根据路由表查询本机到DNS查询消息发送方,大致估算出距离。还有一种方法:在HTTP规格中有一个location字段,当web服务器数据转移到其他服务器时可以使用这个字段,它的意思是“你要访问的数据在另一台服务器,去访问那台服务器吧”这种将客户端访问引导到另一台web服务器的操作叫做重定向。当使用重定向告知客户端最近的缓存服务器时,首先将重定向服务器注册到web服务器端的DNS服务器上,这样,客户端会将HTTP请求消息发送到重定向服务器上。重定向服务器和第一种方法DNS服务器一样,收集路由器的路由信息,根据这些信息找到最近的缓存服务器,然后将缓存服务器的地址放到location字段中返回响应(也可以返回一个通过网络包往返时间估算到缓存服务器的距离的脚本,通过在客户端运行脚本来找到最近的缓存服务器),客户端就会重新去访问指定的缓存服务器了。这种方法缺点是增加了HTTP消息的交互次数,优点是距离的精度较高。
​ 缓存内容的更新方法会影响缓存服务器的效率,有一种方法是让web服务器在原始数据更新时,立即通知缓存服务器,使得缓存服务器上的数据一直保存最新的状态,就不需要每次确认原始数据是否变化,而且从第一次访问就可以发挥缓存的效果。CDS缓存器就具备这种功能。除了事先编写好内容的静态页面之外,还有一些在收到请求后由CGI程序生成的动态页面,这种页面是不能保存在缓存服务器上的,这种情况下,可以不保存整个页面,而是将应用程序生成的部分,也就是动态部分和内容不会变化的静态部分分开,只将静态部分保存在缓存中。

第六章:请求到达Web服务器,响应返回浏览器

​ 在包收发操作中,服务器和客户端是没有区别的。从数据的收发角度来看,客户端和服务器的区别是区分连接和等待这两个不同的角色。服务器将程序分为两个模块,即等待连接模块和负责与客户端通信的模块。每次有新的客户端发起连接,都会启动一个新的客户端通信模块,与客户端是一对一的关系。服务器操作系统具有多进程、多线程功能,同时运行多个程序。(进程是作为单独的程序来对待,而线程是一个程序中的一部分)。服务器的接收操作过程:到达服务器的网络包本质是电信号或光信号,所以接收的第一步是网卡接收到信号,将其还原成数字信息;接下来需要根据包末尾的帧校验序列(FCS)来校验错误,即根据校验公式计算刚刚接收的数字信息和包末尾的FCS值进行比较,FCS值是发送时根据转换成电信号之前的数字信息进行计算得到的,如果根据信号还原的数字信息和发送前的信息一致,则计算机出的FCS也应该和包末尾的FCS一致,不一致则可能是因为噪声等影响导致信号失真,这时接收的包无效,需要丢弃。当一致时,接下来需要检查MAC头部中的接收方MAC地址,看看这个包是不是发送给自己的,不是则丢弃。还原后的数字信息保存在网卡内部的缓冲区,以上操作都是由网卡的MAC模块来完成的。这个过程中CPU是不知道网络包到达的,而且在执行其他任务,但接下来的操作需要CPU参与,所以网卡会通过中断,将网络包到达的事件通知给CPU,接下来CPU会暂停当前的工作,切换到网卡的任务,然后网卡驱动从网卡缓冲区将接收的包读取出来,根据MAC头部的以太类型字段判断协议的种类,并调用负责处理该协议的软件。(这里表示IP协议,就会调用TCP/IP协议栈)
IP模块会检查IP头部,格式是否符合规范,然后检查接收方IP地址,看包是不是发给自己的,确认之后检查包有没有被分片。如果是分片的包,则将包暂时存放到内存中,等分片到达,将其组装还原。如果不是则不需要进行重组。接下来检查IP头部的协议号字段,将包转发给相应的模块,例如是06(十六进制),则将包转交给TCP模块,如果是11(十六进制)则转交给UDP模块。
​ 假设这个包交给TCP模块处理,这个包是发起连接的包。当TCP头部中的控制位SYN为1时,表示这是一个发起连接的包,TCP模块会执行接受连接的操作。不过在之前需要检查包的接收方端口号,确认在该端口号有没有与接收方端口号相同且对待连接状态的套接字,如果没有则返回错误的包。如果存在则为这个套接字复制一个副本,并将发送方IP地址、端口号、序号初始值、窗口大小等必要参数写入这个套接字中,同时分配用于发送缓冲区和接收缓冲区的内存空间。然后生成代表确认接收的ACK号,用于从服务器像客户端发送数据的序号初始值,表示接收缓冲区剩余容量的窗口大小,并用这些信息生成TCP头部,委托IP模块发送给客户端。这个包到达客户端后,客户端会返回表示接收确认的ACK号,连接操作就完成了。这时服务器端程序会进入调用accept暂停状态,当新套接字的描述符转交给服务器程序(通信模块)后,就会恢复运行。

​ 数据收发阶段,TCP会检查收到的包对应哪一个套接字,需要找到发送方IP地址和接收方IP地址,接收方端口号和发送方端口号这4种信息全匹配的套接字,接下来TCP模块会对比该套接字中保存的数据收发状态和收到包的TCP头部的信息是否匹配,以确认数据收发是否正常。具体来说,就是根据套接字中保存的上一个序号和数据长度计算下一个序号,并检查收到的包TCP头部中的序号是否一致。如果一致则说明包正常到了服务器,没有丢失,这是TCP模块会从包提取出数据存放到接收缓冲区和上次的数据块连接起来,这样数据就被还原成分包之前的状态了。当数据进入接收缓冲区,TCP模块会生成确认应答的TCP头部,并根据接收包的序号和数据长度计算出ACK号,然后委托IP模块发送给客户端。数据收发完成后,执行断开操作,具体顺序由应用层协议决定。如果是服务器先断开,会调用socket库的close,TCP模块会生成控制位FIN为1的TCP头部,委托IP模块发送给客户端,当客户端收到会返回一个ACK号,接下来,客户端调用close,生成FIN为1的TCP头部发送给服务器,服务器再返回ACK号,断开操作就完成了。套接字会在一段时间后被删除。
​ 应用程序会调用socket库的read来获取收到的数据,在接受缓冲区的数据块会被转交给应用程序,控制流程会转移到服务器程序,对接收的数据进行处理,也就是检查HTTP请求信息,并根据请求的内容向浏览器返回相应的数据。web服务器公开的目录其实并不是磁盘上的实际目录,而是虚拟目录。根据URI读取文件时需要先查询虚拟目录和实际目录的对应关系,将URI转换成实际的文件名后,才能读取文件并返回数据。有些web服务器程序还有文件名改写的功能,只要设置好改写的规则,当URI中的路径符合改写规则时,就可以将URI中的文件名改写成其他文件名进行访问。(当处于某些原因web服务器的目录和文件名发生变化,但又希望用户通过原来地址进行访问时)(所以说有的网站更新之后,网址可能不一样了,用户是不知道的,依然访问旧的地址,为了让用户访问到网址,有可能会改写,我猜的。)
​ URI指定的文件内容可能是一个程序(CGI程序),(突然明白所以我写的servlet或者说是spring框架的控制器,就是一个CGI程序,然后可能返回数0据或者是html。)WEB服务器会委托操作系统运行这个程序,然后从请求信息中取出数据交给运行的程序。(所以request.getParameter()的作用就是对应这个吧)如果方法为GET,则将URI后面的参数传递给程序,如果为POST,则将消息体中的数据传递给程序。当访问设置了用户名和密码保护的页面时,需要在HTTP请求消息中添加用户名和密码头部字段(Authorization),否则,web服务器不会返回请求页面的内容而是会返回要求提供用户名和密码的头部字段(www-Authorization)的消息
​ 浏览器通过响应的数据类型判断其中的内容属于哪种类型,根据Content-Type字段,还可以结合其他一些信息综合判断,例如文件扩展名,数据内容格式。接下来只要根据数据类型用于显示内容的程序,将数据显示出来就可以了。

看完这本书花了6天,基本是一天一章节

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值