计算机⽹络Web应⽤层与运输层(HTTPTCP)
应⽤层协议原理
Web和HTTP
DNS:英特⽹的⽬录服务
运输层
⾯向连接的运输:TCP及拥塞原理
⼀、应⽤层协议原理
DNS域名解析:
(⽤例:www.baidu)域名解析是⽹络请求的第⼀步操作,DNS域名解析⾸先是在浏览器缓存中匹配历史对应域名的IP地址,如果没有到就到计算机的⽹络访问缓存中匹配,如果还不到匹配的IP地址,就会将域名发送到根权威服务器上(com),然后再根权威服务器上匹配到域名(baidu)的服务器IP地址返回发送回客服端上。
⽹络连接实质上是基于IP地址来建⽴⽹络连接,最后实现数据传送。⽐如我们可以通过控制台然后使⽤ping命令查看到www.baidu的IP 地址,然后可以直接将IP地址输⼊⽹址栏,照样可以获取到百度的主页。例如:
这⾥主要就⽹络访问⼀些过程做⼀些说明,后⾯有对DNS有具体的解析
有了IP地址,相当于才能真正到服务器,IP作为每台⽹络计算机的唯⼀标识。这时候开始尝试建⽴⽹络通路,实现数据传输,也就有了三次握⼿和四次挥⼿的环节。⽹络应⽤通信的实际上进程,web应⽤是由客户端的浏览器进程和web服务器的进程交换报⽂。
套字节:即软件接⼝向⽹络发送报⽂和从⽹络接收报⽂。套字节是同⼀台主机内应⽤层与运输层的接⼝,由于该套字节是建⽴⽹络应⽤程序的可编程接⼝,因此套字节也是应⽤程序和⽹络之间的应⽤程序编程接⼝。应⽤程序开发者可以控制套字节在应⽤层端的⼀切,但是对该套字节的运输层端⼏乎没有控制权。应⽤程序开发者对于运输层的控制权仅限于:1.选择运输层协议;2.也许能设定⼏个运输层参数,如最⼤缓存和最⼤报⽂段长度等。(《计算机⽹络》59页)
除了将报⽂发送到⽬标服务器,还必须指定运⾏在接受主机上的接收进程。也可以说是端⼝号。通常web服务器端⼝号⽤80来标识。
可供应⽤程序使⽤的运输服务:
可靠数据传输:发送进程只要将其数据传递进套字节,就可以完全相信该数据将能⽆差错地到达接收进程。(数据不丢失)
吞吐量:运输层协议能够以某种特定的速率提供确保的可⽤吞吐量,使⽤这种服务能够确保可⽤吞吐量总是为⾄少r⽐特/秒(带宽敏感应⽤:(例)⽹络电话);弹性应⽤能够根据情况或多或少地利⽤可供使⽤的吞吐量。电⼦邮件、⽂件传输、以及web传送都属于弹性应⽤。
定时:运输层能提供定时保证(时间敏感)。因特⽹电话、虚拟环境、电话会议和多⽅游戏都需要严格的事件限制。
安全性:运输协议能够为应⽤程序提供⼀种或多种安全性服务。(对发送进程传输的所有数据加密)
因特⽹(⼀般是TCP/IP⽹络)为应⽤提供两层运输协议,即UDP和TCP。下⾯是常见应⽤程序的服务要求:
应⽤数据丢失带宽时间敏感
⽂件传输不能丢失弹性不
电⼦邮件不能丢失弹性不
Web⽂档不能丢失弹性(⼏kbps)不
因特⽹电话/视频会议容忍丢失⾳频(⼏kbps~1Mbps)/视频
(10kbps~5Mbps)
是,100ms
存储⾳频/视频容忍丢失⾳频(⼏kbps~1Mbps)/视频
(10kbps~5Mbps)
是,⼏秒
交互式游戏容忍丢失⼏kbps~10kbps是,100ms
即时通讯不能丢失弹性是和不是
TCP服务:1.⾯向连接的服务:在应⽤层数据报⽂开始流动之前,TCP让客户和服务器相互交换运输层控制信息。这就是握⼿过程,这条连接是双⼯的,即连接双⽅的进程可以在此连接上同时进⾏报⽂收发。当应⽤程序结束报⽂发送时,必须拆除该链接,也就是挥⼿过程。2.可靠的数据服务,也就是数据
层的可靠数据传输。然后,TCP协议还具有拥塞控制机制,这种服务不⼀定能为通信进程带来直接好处,但能为因特⽹带来整体好处。当发送⽅和接受⽅之间的⽹络出现拥塞时,TCP的拥塞控制机制会抑制发送进程(客户端或服务器)。
UDP服务:是⼀种不提供不必要服务的轻量级运输协议,它仅提供最⼩服务。UDP是⽆法连接,两个进程通信前没有握⼿过程。当进程将⼀个报⽂发送进UDP套字节时,UDP协议并不保证该报⽂将到达接受进程,并且到达接收进程的报⽂也可能是乱序到达。UDP没有拥塞机制,所以UDP的发送端可以⽤选定的任何速率向其下层注⼊数据(实际端到端吞吐量可能⼩于这个速率,这可能是因为中间链路的带宽受限或因为拥塞⽽造成的)。
因特⽹运输协议不提供的服务:吞吐量和定时保证,但不意味着因特⽹电话这样的时间敏感应⽤不能运⾏在因特⽹上,因为因特⽹上运⾏时间敏感应⽤已经有多年了(以后有机会对多媒体⽹络这部分重点分析:)。
流⾏的因特⽹引⽤及其应⽤层协议和⽀撑的运输协议:
应⽤⽤户层协议⽀撑的运输层协议电⼦邮件 SMTP [RFC 5321] TCP
远程终端访问 Telnet [RFC 854] TCP
Web HTTP [RFC 2616] TCP
⽂件传输 FTP [RFC 959] TCP
流式多媒体 HTTP(如YouTube) TCP
web服务器域名是什么因特⽹电话 SIP [RFC 3261]、RTP
[RFC 3550]、或专⽤的(如
Skype)
UDP或TCP
⼆、Web和HTTP协议
Web的应⽤层协议是超⽂本传输协议(HyperText Transfer Protocol,HTTP),它是Web的核⼼,在[RFC 1945]和[RFC 2616]中进⾏了定义。HTTP有两个程序实现:⼀个客户端程序和⼀个服务器程序。客户程序和服务器程序运⾏在不同的端系统中,通过交换HTTP报⽂进⾏会话。HTTP定义了这些报⽂的结构以及客户和服务器进⾏报⽂交换的⽅式。因为HTTP服务器并不保存关于客户的任何信息,假如某个特定
的客户在短短⼏秒钟内两次请求同⼀个对象,服务器也响应两次,将同⼀个对象重复发送给客户,所以HTTP是⼀个⽆状态协议。
持续连接与⾮持续连接:
客户和服务器在⼀个相当长的时间范围内通信,其客户发出⼀系列请求并且服务器对每个请求进⾏响应。这⼀系列的请求可以以规则的间隔周期性地或者间断性地⼀个接⼀个发出。当客户与服务的交互时,每个请求/响应是经单独的TCP连接发送还是所有请求即响应都是经过相同的⼀个TCP连接发送。每个单独的TCP连接被称为⾮持续连接,经过相同的⼀个TCP连接被称为持续连接,持续连接在⼀定时间内没有发⽣请求HTTP服务器就会关闭连接。HTTP能够使⽤⾮持续连接也能使⽤持续连接,各有优缺点。
每⼀个HTTP请求都需要经过三次握⼿建⽴连接传输⽂件,这个过程需要两次往返时间(RTT),会产⽣⼀定的⽹络延时。持续连接可以在⼀定程度上减少这种重复的握⼿连接过程,但是多个请求采⽤⼀个TCP连接需要等待⼀个⼀个的传输,在⼀定程度上可以减少⽹络延时,但也产⽣了等待执⾏的时间。持续连接相对⾮持续连接在很⼤程度上减少了服务器的压⼒,但是性能问题是由多种因素造成的,量化⽐较持续连接和⾮持续连接对于优化性能⾮常有必要(《计算机⽹络》69页)参考⽂献[Heidemann 1997; Nielsen 1997]。
这就是常说的三次握⼿过程,这个过程我们需要重点关注的是往返时间(RTT)和传输⽂件的时间,这也是web开发中优化的重要部分。第⼀次握⼿:客服端发起TCP连接;第⼆次握⼿:服务端响应连接;第三次握⼿:客服端请求⽂件;接下来就是服务端响应⽂件请求,开始⽂件传输。
HTTP报⽂:
GET /somedir/page.html HTTP/1.1
Host: www.someschool.edu
Connection: close
User-agent:Mozilla/5.0
Accept-language: fr
报⽂使⽤普通的ASCII⽂本书写的,上⾯是个请求报⽂内容总共就5⾏代码,每⾏由⼀个回车和换⾏符结束,最后⼀⾏后⼀⾏后再附加⼀个回车换⾏符。第⼀⾏叫做请求⾏,第⼆⾏叫做⾸部⾏,Connection表⽰连接⽅式,User-agent⽤来指明代理,Accept-language表⽰想获得对象的语法版本。
请求⾏三个字段:⽅法字段、URL字段、HTTP版本字段。⽅法字段可取⼏种不同的值,包括GET、POST、HEAD、PUT和DELETE。URL字段带有请求对象的标识(page.html),这⾥的版本字段实现的是HTTP/1.1版本。
⾸部⾏Host指明了对象所在的主机,⾸部提供的信息是Web代理⾼速缓存所要求的。其他的部分再HTTP协议分析博客中具体解析。
请求报⽂格式:
HTTP/1.1 200 OK
Connection: close
Date:tue, 09 Aug 2011 15:44:04 GMT
Server:Apache/2.2.3(CentOS)
Last-Modified:Tue, 09 Aug 2011 15:11:03 GMT
Content-length:6821
Content-Type:text/html
(data data data data data ...)
响应报⽂的第⼀⾏是状态⾏,然后是⾸部(这⾥⾸部共六⾏),然后是实体(响应实体)。
状态⾏三个字段:协议版本字段、状态码字段、相应状态信息。这⾥重点提⼀下状态码和相应状态信息,然后响应⾸部到HTTP协议分析博客中具体介绍。下⾯是⼀些常见的状态码和相关的短语:
200 OK:请求成功,信息在返回的响应报⽂中。
301 Moved Permanently:请求的对象已经被永久转移了,新的URL定义在响应报⽂的Location:⾸部中。客户软件将⾃动获取新的URL。
400 Bad Request:⼀个通⽤查错代码,指⽰该请求不能被服务器理解。
404 Not Found:被请求的⽂档不在服务器上。
505 HTTP Version Not Supported:服务器不⽀持请求报⽂中的HTTP协议。
最后介绍在window上的⽹络请求命令:curl 。这篇博客介绍了curl的⽤法。
⽤户与服务器的交互:cookie
前⾯提到HTTP服务器是⽆状态的,那同时处理数千计甚⾄更⼤的访问时怎么识别⽤户呢?当然你可以使⽤关系型数据库记录的⽤户标识,如果你不考虑性能的话可以这么做。现在HTTP协议有⼀种存在请求报⽂上的识别标识,相对来说就好多了,这就是cookie,cookie是由服务端通过HTTP协议和浏览器设置在客户端的⼀个标识,这个标识可以设置⼀些简单的信息,还可以设置它的⽣命周期。
但是cookie并不是最佳选择,因为cookie不安全⽽且浏览器可以主动设置屏蔽cookie,所以这时候⼜有了服务端的session,这已经不在HTTP范畴了,后期相关博客具体介绍cookie和session的使⽤⽅法再解析。随着技术的进步,web基于HTTP的⽆状态解决⽅案也越来越多,有机会再详细介绍。
如果本地缓存了⽤户某个站点的cookie信息,在⽤户每次登⼊该站点时HTTP报⽂头部都会通过cookie头部⾏传送给服务器,服务器通过Set-cookie响应头部⾏设置客户端的cookie。
web缓存
web缓存器(Web cache)也叫代理服务器(proxy server),它是能够代表初始Web服务器来满⾜HTTP请求的⽹络实体。Web缓存器有⾃⼰的磁盘存储空间,并在存储空间中保存最近请求过的对象的副本,使得⽤户所有HTTP请求⾸先指向Web缓冲器。下⾯具体描述客户端通过web缓存器请求资源的全部经过:
浏览器建⽴⼀个到Web缓存器的TCP连接,并向Web缓存器中的对象发送⼀个HTTP请求。
Web缓存器进⾏检查,看看本地是否存储了该对象副本。如果没有,Web缓存器就向客户端浏览器⽤HTTP响应报⽂返回该对象。
如果Web缓存器中没有该对象,它就打开⼀个与该对象的初始服务器的TCP连接。Web缓存器则在这个缓存器到服务器的TCP连接上发送⼀个对该对象的HTTP请求。在收到该请求后,初始服务器向该Web缓冲器发送具有该对象的HTTP响应。
当Web缓存器接收到该对象时,它在本地存储空间存储⼀根副本,并向客户的浏览器⽤HTTP相应报⽂发送该副本(通过现有的客户端浏览器和Web缓存器之间的TCP连接)。
web缓存器通过使⽤内容分发⽹络(Content Distri-bution Network, CDN)实现,CDN公司在因特⽹上安装了许多地理上分散的缓冲器,因⽽使⼤流量实现本地化。
经过上⾯的过程描述,web缓存器在响应客户端请求时就是⼀个服务器,⽽在向初始服务器发送请求时就是⼀个客户端。这样的⽹络响应⽅式肯定是可以很⼤程度的提⾼响应效率,具体可以了解(《计算机⽹络》75页)。但是这样的⽹络响应就会存在⼀个问题,怎么确保web缓存的副本是最新的最新的资源呢?什么时候更新web缓存器的副本?
在Web缓存器上,HTTP协议有⼀种机制,允许缓存器证实它的对象是最新的。这种机制就是get⽅法,如果请求报⽂使⽤get⽅法,并且请求报⽂中含有“If-Modified-since:”⾸部⾏,那么这个请求报⽂就是⼀个条件get请求报⽂。下⾯是是⼀对Web缓存器的HTTP请求和响应报⽂:
GET /fruit/kiwi.gif HTTP/1.1
iquecuisine
If-Modified-since:web, 7 Sep 2011 09:23:24
//初始服务器响应
HTTP/1.1 304 Not Modified
Date: Sat, 15 Oct 2011 15:39:29
Server: Apache/1.3.0 (Unix)
(empty entity body)
三、DNS:因特⽹的⽬录服务
DNS( Domain Name System)是“域名系统”的英⽂缩写,是⼀种组织成域层次结构的计算机和⽹络服务命名系统,它⽤于TCP/IP⽹络,它所提供的服务是⽤来将主机名和域名转换为IP地址的⼯作。俗话说,DNS就是将⽹址转化为对外的IP地址。
第⼀步:浏览器将会检查缓存中有没有这个域名对应的解析过的IP地址,如果有该解析过程将会结束。浏览器缓存域名也是有限制的,包括缓存的时间、⼤⼩,可以通过TTL属性来设置。
第⼆步:如果⽤户的浏览器中缓存中没有,操作系统会先检查⾃⼰本地的hosts⽂件是否有这个⽹址映射关系,如果有,就先调⽤这个IP地址映射,完成域名解析。
第三步:如果hosts⾥没有这个域名的映射,则查本地DNS解析器缓存,是否有这个⽹址映射关系,如果有,直接返回,完成域名解析。
第四步:如果hosts与本地DNS解析器缓存都没有相应的⽹址映射关系,⾸先会TCP/ip参数中设置的⾸选DNS服务器,在此我们叫它本地DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。
第五步:如果要查询的域名,不由本地DNS服务器区域解析,但该服务器已缓存了此⽹址映射关系,则调⽤这个IP地址映射,完成域名解析,此解析不具有权威性。
第六步:如果本地DNS服务器本地区域⽂件与缓存解析都失效,则根据本地DNS服务器的设置(是否设置转发器)进⾏查询,如果未⽤转发模式,本地DNS就把请求发⾄13台根DNS,根DNS服务器收到请求后会判断这个域名()是谁来授权管理,并会返回⼀个负责该顶级域名服务器的⼀个IP。本地DNS服务器收到IP信息后,将会联系负责域的这台服务器。这台负责域的服务器收到请求后,如果⾃⼰⽆法解析,它就会⼀个管理域的下⼀级DNS服务器地址给本地DNS服务器。当本地DNS服务器收到这个地址后,就会域名域服务器,重复上⾯的动作,进⾏查询,直⾄到域名对应的主机。
第七步:如果⽤的是转发模式,此DNS服务器就会把请求转发⾄上⼀级DNS服务器,由上⼀级服务器进⾏解析,上⼀级服务器如果不能解析,或根DNS或把转请求转⾄上上级,以此循环。不管是本地DNS服务器⽤是是转发,还是根提⽰,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。
这部分直接拷贝别⼈的了,对于DNS不是三⾔两语就能解释清楚的,前期学习也不会有太多接触,有机会在重点解析。有兴趣可以先了解⼀下这篇⽂章,我这篇博客的DNS部分的内容也是从这⾥拷贝的。
四、运输层/TCP、UDP
⼀个Web请求经过了HTTP请求到DNS域名解析后就到了向服务器发起正式的资源请求了,HTTP报⽂经过套字节向⽹络发送请求报⽂,这时候就开始基于TCP协议来进⾏⽹络运输层的资源交互响应了。
运输层概述
运输层协议为运⾏在不同主机上的应⽤进程之间提供逻辑通信,从应⽤程序的⾓度看,通过逻辑通信,运⾏不同进程的主机好像直接连接⼀样。简单的说就是通过运输层协议将两个不同的主机和不同的进程通过逻辑处理,让它们相互连接进⾏报⽂段交付和数据传输。
运输层协议是在端系统中⽽不是在路由器中实现(也就是你的客户主机或者服务器主机)。
在发送端,运输层将从发送应⽤程序进程接收到的报⽂转换成运输层分组(报⽂段),实现的⽅法是将应⽤报⽂划分成较⼩的块,并为每块加上⼀个运输层⾸部⽣成运输层报⽂段。
然后,在发送端系统中,运输层将这些报⽂段传递给⽹络层,⽹络层将其封装成⽹络层分组(数据报)并向⽬的地发送。
⽹络路由仅作⽤于该数据报的⽹络层字段;即他们不检查封装在数据报的运输层报⽂段的字段。
在接收端,⽹络层从数据报中提取运输层报⽂段,并将该报⽂段向上交给运输层。
运输层则处理接收到的报⽂段,使该报⽂段中的数据为接收应⽤进程使⽤。
整个运输层就是从发送端的进程接收报⽂然后转换成报⽂段,然后再将报⽂段交给⽹络层发送到⽬的地,然后接收端的运输层拿到报⽂段交给对应的应⽤程序进程。这个过程⾥⾯有⼀个问题值得探讨,就是运输层如何从进程拿到报⽂,拿到报⽂后转换成报⽂段做了什么。接收端的运输层接收到报⽂段⼜是如何将报⽂段交给应⽤程序进程的。我们知道⼀台主机会有很多个应⽤程序进程,运输层如何分辨,将报⽂段准确⽆误的交给对应的应⽤程序进程。这就是我们接下来要介绍的:运输层多路复⽤与多路分解。
上⾯我们介绍了运输层是在端系统上进⾏逻辑处理来实现两个端系统的进程连接,那么就有必要来了解运输层协议到底是如何进⾏逻辑处理的。
运输层的多路复⽤与多路分解,将两个端系统间IP的交付服务扩展未运⾏在端系统上的进程交付服务。
每个运输层报⽂段中具有⼏个字段,在接收端运输层检查这些字段,标识出接收套字节,进⽽将报⽂段定向到该套字节,这就是多路分解,也是接收端的运输层逻辑。
在源主机(客户主机)从不同套接字中收集数据块,并为每个数据块封装上⾸部从⽽⽣成报⽂段,然后将报⽂段传送到⽹络层,这就是多路复⽤。
上⾯的运输层实套接字有些是⽬的IP地址和⽬的端⼝号组成的⼆元组标识,有些会多包含有源端⼝IP地址和源端⼝号的四元组标识,这其中的区别就是下⾯要解释的⽆连接和有链接的多路复⽤和多路分解。
⽆连接的多路复⽤与多路分解:UDP套接字是由⼆元组来标识的,所以UDP是⽆连接运输协议。
有链接的多路复⽤与多路分解:CTP套接字是由四元组来表⽰的,所以CTP是有链接运输协议。
下⾯是⼀个TCP运输的Web请求过程:
TCP服务器应⽤程序有⼀个“welcoming socket”,它在12000号端⼝上等待来⾃TCP客户的连接建⽴请求。
TCP客户使⽤下⾯的代码创建⼀个套接字并发送⼀个连接建⽴请求报⽂段:clientSocket = socket(AF_INET,
SOCK_STREAM);t((serverName,12000))
⼀条连接建⽴请求只不过是⼀个⽬的端⼝号为12000,TCP⾸部的特定“连接位置”置位的TCP报⽂段,这个报⽂段也包含⼀个客户选择的源端⼝号。(后⾯有具体的解析)
当运⾏服务器进程的计算机的主机操作系统接收到了具有⽬的端⼝12000的⼊连接请求报⽂段后,它就定位服务器进程,该进程正在端⼝号12000等待接收连接。该服务器进程创建⼀个新的套接字:connectionSocket, addr = serverSocket.accept()
该服务器的运输层还注意到连接请求报⽂段中的下列四个值:1.该报⽂段中的源端⼝号;2.源主机IP地址;3.该报⽂段中的⽬的端⼝号;4.⾃⾝的IP地址。
新创建的连接套接字通过这4个值来标识。所有后续到达的报⽂段,如果他们的源端⼝号、源主机IP地址、⽬的端⼝号和⽬的IP地址与这4个值匹配,则被分解到这个套字节。随着TCP连接完成,客户和服务器可以开始互相发送数据了。(服务器主机⽀持很多并⾏的TCP套接字,每个套接字与⼀个进程相联系,并由其四元组来标识每个套接字,所有4个资源被⽤来将报⽂段定向(分解)到响应的套接字)
⽆连接的运输:UDP/⾯向连接的运输:TCP
由于运输层的内部机制和实现原理篇幅不少,⽽且有⾮常重要,同时也为了⽅便以后查阅,特将这部分内容分别独⽴储出去作为两个博客内容,下⾯是这两篇博客的连接:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。