TCP报头格式
定义:TCP传输控制协议是一种面向连接的、可靠的、基于字节流的传输层协议。
图一是TCP报文格式,下面是对各参数的解释
- 源端口号和目的端口号:TCP报头中的源端口号和目的端口号同IP数据报中的源IP与目的IP唯一确定一条TCP连接
- 序号:用来标识TCP发端向TCP收端发送的数据字节流
- 确认序号:ACK标志位为1时确认序号才有效(即不为0);一旦连接建立,该值将始终发送
- 首部长度:报文头长度(单位:bit)/32
例子:1000(转化为十进制为8,8 * 32/8 = 32,该报文报头长度为32个字节)
存在该字段是因为TCP报头中任选字段长度可变
报头不包含任何任选字段则长度是20字节;4位所能表示的最大值为1111,转换为十进制是15,15*32/8 = 60,故报头最大长度是60字节 - 保留:占6位,保留为今后使用,目前应置为0
- 控制位:6位
- URG:紧急指针有效性标志
- ACK:确认序号有效性标志,一旦一个连接建立起来,该标志位总被置为1,即除了请求建立连接报文(仅设置SYN标志位为1),其他所有报文的该标志位总为1
- PSH(PuSH):推送标志位,接收方应尽快将报文段提交至应用层,而不再等到整个缓存都填满了后再向上交付
- RST(ReSeT):重置连接标志位,当RST=1时,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立运输连接
- SYN:同步序号标志
- FIN:传输数据结束标志
- 窗口大小(2字节):TCP流量控制通过连接的每一个端声明窗口大小进行控制(接受缓冲区大小)
由于2字节能够表示的最大正整数为65535,故窗口最大值为65535 - 检验和(2字节):检验和覆盖整个TCP报文段;强制字段,有发送端计算存储,有接收端进行验证
- 紧急指针(2字节):当URG=1时,紧急指针才有效
- 选项(0-40字节):当没有使用“选项”时,TCP的首部长度是20字节
TCP的三次握手与四次挥手
-
三次握手:
**第一次握手:**主机A发送位码为SYN=1,随机产生seq number=10001的数据包到服务器,主机B由SYN=1知道A要求建立联机,此时状态为SYN_SENT;**第二次握手:**主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),SYN=1,ACK=1,随机产生seq number=20001的包,此时状态有LISTEN变为SYN_RECV;
**第三次握手:**主机A收到后检查ack number是否正确,即第一次发送的seq number + 1,以及位码ack是否为1,若正确,主机A会再次发送ack number = (主机B的seq+1),ACK=1,主机B收到后确认seq值与ack=1则连接建立成功,双方状态established
完成三次握手,主机A与主机B开始传送数据。
各个状态名称与含义
- CLOSED:表示初始状态
- LISTEN:表示服务器端的某个socket处于监听状态,可以接受连接了
- SYN_RECV:这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务端的socket在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat你是很难看到这个状态的。这种状态时,当收到客户端的ACK报文后,它会进入到established
- SYN_SENT:这个状态与SYN_RECV遥相呼应,当客户端socket执行connect连接时,它首先发送SYN报文,因此也随机它会进入到了SYN_SENT状态,并等到服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文
- ESTABLISHED:表示连接已经建立了。
-
四次挥手:
假设Client端发起中断请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说“我client端要发给你了”,但是如果你还没有数据要发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,“告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息”。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,“告诉Client端,好了,我这边数据发完了,准备好关闭连接了”。Client端收到FIN报文后,“就知道可以关闭连接了,但是它还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。”,Server端收到ACK后,“就知道可以断开连接了”。Client端等待2MSL(报文最大生存时间)后仍然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。这样,TCP连接就这样关闭了。
各个状态名称与含义:
- FIN_WAIT_1:其实FIN_WAIT_1与FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。这两种状态的区别是:FIN_WAIT_1状态实际上是当Socket在established状态时,它想主动关闭连接,向对方发送FIN报文,此时该socket即进入FIN_WAIT_1状态。而当对方回应ACK报文后,则进入FIN_WAIT_2状态。当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态比较难见,而FIN_WAIT_2状态可以用netstat看到。
- FIN_WAIT_2:实际上该状态下的socket,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有些数据要传,稍后再关闭连接。
- TIME_WAIT:表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,则可直接进入TIME_WAIT状态,而无需经过FIN_WAIT_2状态。
下面两个问题记牢
为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
*第一种回答:*这是因为服务端的listen状态下的socket当收到SYN报文的连接请求时后,它可以把ACK和SYN(ACK起到应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了,但未必你所有的数据都全部发送给对方了,所以你可以未必会关闭socket连接,也即你可能还需要发送一些数据给对方之后,在发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
*第二种回答:*因为当Server端收到Client端的SYN连接请求后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭Socket,所以只能先回复一个ACK报文,告诉client端,“你发送的FIN报文我收到了”。只有等到Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送,故需要四次挥手。
为什么TIME_WAIT状态还需要等待2MSL后才能返回到CLOSED状态?
答:因为虽然双方都同意关闭连接了,而且握手的4个报文也都发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SENT状态到ESTABLISH状态那样),但是我们必须假想网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
UDP报头格式
源端口号:在需要对方回信时选用。不需要是可全为0
目的端口号:这在终点交付报文时必须要使用到
UDP长度:UDP报文的字节长度(包括首部和数据)
UDP校验和:检验UDP首部和数据部分的正确性
TCP/UDP区别
课本:
UDP在传输数据之前不需要先建立连接。远程主机的运输层在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP却是一种最有效的工作方式。
TCP则提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP不提供广播或多播服务。由于TCP要提供可靠地、面向连接的运输服务,因此不可避免地增加了许多的开销,如确认、流量控制、计时器以及连接管理等。这不仅使协议数据单元的首部增大很大,还要占用许多的处理机资源。
博客答案:
TCP | UDP | |
---|---|---|
是否连接 | 面向连接 | 面向非连接 |
传输可靠性 | 可靠的 | 不可靠的 |
应用场合 | 传输大量的数据 | 少量数据 |
速度 | 慢 | 块 |
OSI和TCP/IP模型在传输层定义两种传输协议:TCP(传输控制协议)和UDP(用户数据报协议)。
UDP
UDP和TCP的主要区别在于UDP不一定提供可靠的数据传输。事实上,该协议不能保证数据准确无误地到达目的地。UDP在很多方面非常有效。当某个程序的目标是尽快地传输尽可能多的信息时(其中任意给定的重要性相对较低),可使用UDP。许多程序将使用单独的TCP连接和单独的UDP连接。重要的状态信息随可靠的TCP连接发送,而主数据留通过UDP发送。
TCP
TCP的目的是提供可靠的数据传输,并在相互进行通信的设备或服务之间保持一个虚拟连接。TCP在数据包接收无序、丢失或在交付期间被破坏时,负责数据恢复。它通过为其发送的每个数据包提供一个序号来完成此恢复。较低的网络层会将每个数据包视为一个独立的单元,因此,数据包可以沿完全不同的路径发送,即使它们都是同一消息的组成部分。这种路由与网络层处理分段和重新组装数据包的方式非常相似,只是级别更高而已。
为确保正确地接收数据,TCP要求在目标计算机成功收到数据时发回一个确认(即ACK)。如果在某个时限内未收到相应的ACK,将重新传送数据包。如果网络阻塞,这种重新传送将导致发送的数据包重复。但是,接收计算机可使用数据包的序号来确认它是否为重复数据包,并在必要时丢弃它。
TCP与UDP的选择:
如果比较UDP包和TCP包的结构,很明显UDP包不具备TCP包复杂的可靠性和控制机制。与TCP协议相同,UDP的源端口数和目的端口数也都支持一台主机上的多个应用。一个16位的UDP包包含了一个字节长的头部和数据的长度,校验码域使其可以进行整体校验。(许多应用只支持UDP,如:多媒体数据流,不产生任何额外的数据,即使知道有破坏的包也不进行重发。)很明显,当数据传输的性能必须让位于数据传输的完整性、可控制性和可靠性时,TCP协议是首选。当强调性能而不是传输的完整性时,如:音频和多媒体应用,UDP是最好的选择。在数据传输时间很短,以至于此前的连接过程成为整个流量主体的情况下,UDP较低的开销使其有更好的机会去传送管理数据。TCP丰富的功能有时会导致不可预料的性能低下,但是我们相信在不远的将来,TCP可靠的点对点将会用于绝大多数的网络应用。
TCP协议和UDP协议特性区别总结:
- TCP协议在传送数据段的时候要给段标号;UDP不需要
- TCP协议可靠;UDP协议不可靠
- TCP协议是面向连接的;UDP协议采用无连接
- TCP协议负载较高,采用虚电路;UDP采用无连接
- TCP协议的发送方要确认接收方是否收到数据段(3次握手协议)
- TCP协议采用窗口技术和流控制
HTTP状态码
当浏览器访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。
HTTP状态码的英文为HTTP Status Code。下面是常见的HTTP状态码:
- 200 请求成功
- 301 资源(网页等)被永久转移到其他URL
- 404 请求的资源(网页等)不存在
- 500 内部服务器错误
状态码分类
分类 | 分类描述 |
---|---|
1** | 信息,服务器收到请求,需要请求者进行执行操作 |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
状态码列表
状态码 | 状态码英文名称 | 中文描述 |
---|---|---|
100 | Continue | 继续,客户端应继续其请求 |
101 | Switching Protocols | 切换协议。服务器根据客户端的请求切换协议。只能切换到HTTP的新版本协议 |
200 | OK | 请求成功。一般用于GET和POST请求 |
201 | Created | 已创建。成功请求并创建了新的资源 |
202 | Accepted | 已接受。已经接受请求,但未处理完成 |
203 | Non-Authoritative Information | 非授权信息。请求成功,但返回的meta信息不在原始的服务器,而是一个副本 |
204 | No Content | 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 |
205 | Reset Content | 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清楚浏览器的表单域 |
206 | Partial Content | 部分内容。服务器成功处理了部分GET请求 |
300 | Multiple Choices | 多种选择。请求的资源可包含多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择 |
301 | Moved Permanently | 永久移动。请求的资源已被永久的移动到新URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 |
302 | Found | 临时移动。与301类似,但资源只是临时被移动,客户端应继续使用原有URI |
303 | See Other | 查看其它地址,与301、302类似,如果最初的请求是POST,那么新文档要用GET找到 |
304 | Not Modified | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 |
305 | Use Proxy | 使用代理,所请求的资源必须通过代理访问 |
306 | Unused | 已经被废弃的HTTP状态码 |
307 | Temporary Redirect | 临时重定向。与302类似,使用GET请求重定向 |
400 | Bad Request | 客户端请求的语法错误,服务器无法理解 |
401 | Unauthorized | 请求要求用户的身份认证 |
402 | Payment Required | 保留 |
403 | Forbidden | 服务器理解请求客户端的请求,但是拒绝执行此请求 |
404 | Not Found | 服务器无法根据客户端的请求找到资源(网页),通过此代码,网站设计人员可设置“您所请求的资源无法找到”的个性页面 |
405 | Method Not Allowed | 客户端请求中的方法被禁止 |
406 | Not Acceptable | 服务器无法根据客户端请求的内容特性完成请求 |
407 | Proxy Authentication Required | 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权 |
408 | Request Time-out | 服务器等待客户端发送的请求时间太长,超时 |
409 | Conflict | 服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突 |
410 | Gone | 客户端请求的资源已经不存在,410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置 |
411 | Length Required | 服务器无法处理客户端发送的不带Content-Length的请求信息 |
412 | Precondition Failed | 客户端请求信息的先决条件错误 |
413 | Request Entity Too Large | 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连接请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息 |
414 | Request-URI Too Large | 请求的URI过长(URI通常为网址),服务器无法处理 |
415 | Unsupported Media Type | 服务器无法处理请求附带的媒体格式 |
416 | Requested range not satisfiable | 客户端请求的范围无效 |
417 | Expectation Failed | 服务器无法满足Expect的请求头信息 |
500 | Internal Server Error | 服务器内部错误,无法完成请求 |
501 | Not Implemented | 服务器不支持请求的功能,无法完成请求 |
502 | Bad Gateway | 充当网关或代理的服务器,从远端服务器接收到了一个无效的请求 |
503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 |
504 | Gateway Time-out | 充当网关或代理的服务器,未及时从远端服务器获取请求 |
505 | HTTP Version not supported | 服务器不支持请求的HTTP协议的版本,无法完成处理 |
HTTP协议
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传送协议。
HTTP是一个基于TCP/IP通信协议来传递数据(HTML文件、图片文件、查询结果等)。
主要特点
- 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、POST。
- 灵活:HTTP允许传输任意类型的数据对象,正在传输的类型由Content-Type加以标记
- 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传输的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
- 支持B/S及C/S
HTTP之URL
HTTP使用统一资源标识符(Uniform Resource Identifiers,URI)来传输数据和建立连接。URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息。
URL,全称是Uniform Resource Locator,中文叫统一资源定位符,是互联网上用来标识某一处资源的地址。
-
URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。
Web上可用的每种资源如HTML文档、图像、视频片段、程序等都是一个来URI来定位的URI一般有三个部分组成:- 访问资源的命名机制
- 存放资源的主机名
- 资源自身的名称,有路径标识,着重强调于资源
-
URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。
URL是Internet上用来描述资源信息的字符串,主要用在各种WWW客户程序客户程序和服务器程序上。采用URL可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。URL一般由三部分组成:
- 协议(或称为服务方式)
- 存有该资源的主机IP地址(有时也包括端口号)
- 主机资源的具体地址。如目录和文件名等
-
URN,uniform resource name,统一资源命名,是通过名字来标识资源
URI是一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式。URL和URN都是一种URI。笼统地说,每个URL都是URI,但不一定每个URI都是URL。这是因为URI还包括一个子类,即统一资源名称(URN),它命名资源但不指定如何定位资源。
在Java的URI中,一个URI实例可以代表绝对的,也可以相对的,只要它符合URI的语法规则。而URL类则不仅符合语义,还包括了定位该资源的信息,因此它不能是相对的。
在Java类库中,URI类不包括任何访问资源的方法,它唯一的作用就是解析。相反的是,URL类可以打开一个到达资源的流。
HTTP之请求信息Request
客户端发送一个HTTP请求到服务器的请求信息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成。
HTTP之响应消息Response
一般情况下,服务器接收并处理客户端发过来的请求后返回一个HTTP的响应消息。HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
1 | 200 OK //客户端请求成功 |
HTTP工作原理
HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。
以下是HTTP请求/响应的步骤:
- 客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认是80)建立一个TCP套接字连接。 - 发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4个部分组成。 - 服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4个部分组成。 - 释放连接TCP连接
若connection模型为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection模型为keep alive,则该连接会保持一段时间,则该时间内可以继续接受请求。 - 客户端浏览器解析HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
例如:在浏览器地址栏键入URL,按下回车之后会经历以下流程:
① 浏览器向DNS服务器请求解析该URL中的域名所对应的IP地址;
② 解析出IP地址后,根据该IP地址和默认端口80,和服务器建立TCP连接;
③ 浏览器发出读取文件(URL中域名后面部分对应的文件)的HTTP请求,该请求报文作为TCP三次握手的第三个报文的数据发送给服务器;
④ 服务器对浏览器请求作出响应,并将对应的HTML文本发送给浏览器;
⑤ 释放TCP连接
⑥ 浏览器将该HTML文本显示
GET和POST请求的区别
- GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连;POST方法是把提交的数据放在HTTP包的body里面;
- GET提交的数据大小有限制(HTTP协议没有对传输的数据大小进行限制,HTTP协议规范也没有对URL长度进行限制,只是由于浏览器对URL的长度有限制),而POST方法提交的数据没有限制;
- GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值;
- GET方式提交数据,会带来安全问题
- GET方式通过一次HTTP请求即可获得数据;POST方式通过两次HTTP请求获得数据,第一次返回状态码100表示浏览器继续请求。
OSI协议、TCP/IP协议以及每层对应的协议
OSI分层 (7层):物理层、数据链路层、网络层、传输层、会话层、表示层、应用层;
TCP/IP分层(4层):网络接口层、 网际层、运输层、 应用层;
5层协议 (5层):物理层、数据链路层、网络层、运输层、 应用层;
session机制、cookie机制
由于http协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是session。这个session是保存在服务端的,有一个唯一标识。在服务端保存session的方法有很多,内存、数据库、文件都可以。
每次http请求的时候,客户端都会发送相应的cookie信息到服务端,实际上大多数的应用都是用cookie来实现session跟踪的,第一次创建session的时候,服务端会在http协议中告诉客户端,需要在cookie里面记录一个session id,以后每次请求把这个会话id发送到服务器。
如果客户端浏览器禁用了cookie,在这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次http请求,URL后面都会附上一个诸如sid=xxx这样的参数,服务端据此来标识用户。
总结:Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
打开网页到页面显示之间的过程
DNS解析
解析过程
DNS解析是一个递归查询的过程
上图是查找www.google.com的IP地址流程。首先在本地域名服务器中查询IP地址,如果没有找到的情况下,本地域名服务器会向根域名服务器发送一个请求,如果根域名服务器也不存在该域名时,本地域名会向com顶级域名服务器发送一个请求,依次类推下去。直到最后本地域名服务器得到google的IP地址并把它缓存到本地,供下次查询使用。从上述过程中,可以看出网址的解析是一个从左向右的过程:com->google.com->www.google.com。事实上,真正的网址是www.google.com.,最后一个.对应的就是根域名服务器,默认情况下,通常会省略,浏览器在请求DNS的时候都会自动加上,所有网址真正的解析过程是:.->.com->google.com.->www.google.com.
。
DNS优化
DNS缓存
DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种:浏览器缓存、系统缓存、根域名服务器缓存、顶级域名服务器缓存、主域名服务器缓存
DNS负载均衡
DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡,又叫做DNS重定向。CDN(Content Delivery Network)就是利用DNS的重定向技术,DNS服务器会返回一个跟用户最接近的点的IP返回给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容。
TCP连接
HTTP协议是使用TCP作为其传输层协议的,当TCP出现瓶颈时,HTTP也会受到影响。
HTTPS协议
HTTP报文是包裹在TCP报文中发送的,服务器端收到TCP报文时会解包提取出HTTP报文。但是这个过程中存在一定的风险,HTTP报文是明文,如果中间被截取的话会存在一定信息泄露的风险。HTTPS协议的本质就是HTTP+SSL(or TLS)。在HTTP报文进入TCP报文之前,先使用SSL对HTTP报文进行加密。从网络的层次结构中看它位于HTTP协议与TCP协议之间。
https在传输数据之前需要客户端与服务端进行一个握手(TCL/SSL握手),在握手过程中将确立双方加密传输数据的密码信息。TCL/SSL使用了非对称加密,对称加密和hash等。具体过程见的阮一峰先生的博客图解SSL/TLS协议
HTTP请求
发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议发送到服务器指定端口(80和443)。HTTP请求报文是由三部分组成:请求行、请求报头和请求正文。
服务器处理请求并返回HTTP报文
后端从在固定的端口接收到TCP报文开始,这一部分对应于编程语言中的socket。它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。这一部分工作一般由Web服务器去进行处理,有Tomcat、Jetty和Netty等。
HTTP响应报文也是由三部分组成:状态码、响应报头和响应报文。
浏览器解析渲染页面
浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repain(重绘)。DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain。页面在首次加载时必然会经历reflow和repain。
JS的解析是由浏览器中的JS解析引擎完成的。JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。JS的执行机制就可以看做是一个主线程加上一个任务队列(task queue)。同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈;异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫做事件循环(Event loop)。
浏览器在解析过程中,如果遇到请求外部资源时,如图像,iconfont,JS等。浏览器将重复1-6过程下载该资源。请求过程是异步的,并不会影响HTML文档进行加载,但是当文档加载过程中遇到JS文件,HTML文档会挂起渲染过程,不仅要等到文档中JS文件加载完毕还要等待解析执行完毕,才会继续HTML的渲染过程。原因是因为JS有可能修改DOM结构,这就意味着JS执行完成前,后续所有资源的下载是没有必要的,这就是JS阻塞后续资源下载的根本原因。CSS文件的加载不影响JS文件的加载,但是却影响JS文件的执行。JS代码执行前浏览器必须保证CSS文件已经下载并加载完毕。
Web优化
如何尽快的加载资源?答案就是能不从网络中加载的资源就不从网络中加载,当我们合理使用缓存,将资源放在浏览器端,这是最快的方式。如果资源必须从网络中加载,则要考虑缩短连接时间,即DNS优化部分;减少响应内容大小,即对内容进行压缩。另一方面,如果加载的资源数比较少的话,也可以快速的响应用户。当资源到达浏览器之后,浏览器开始进行解析渲染,浏览器中最耗时的部分就是reflow,所以围绕这一部分就是考虑如何减少reflow的次数。
补充:
-
一个完整的HTTP请求,通常有以下7个步骤
- 建立TCP连接
- web浏览器向web服务器发送请求命令
- 浏览器发送请求头信息
- 服务器应答
- 服务器发送应答头信息
- 服务器向浏览器发送数据
- 服务器关闭TCP连接
-
一个HTTP请求由四部分组成
- HTTP请求方法或动作,如:GET与POST
- 正在请求的URL
- 请求头,包含一些客户端环境信息、身份验证信息
- 请求体,即请求正文,可包含提交的查询字符串信息、表单信息等。
-
一个HTTP响应一般由三个部分组成
- 一个数字和文字组成的状态码,用来显示请求成功还是失败
- 响应头,包含许多有用的信息,如:服务器类型、日期时间、内容类型和长度
- 响应体,即响应正文。
-
readyState属性(返回请求的当前状态)
- 0,请求未初始换,open还没有调用
- 1,服务器连接已建立,open已经调用
- 2,请求已接收,即接收到头部信息
- 3,请求处理中,即接收到响应体了
- 4,请求已完成,且响应已就绪,即响应完成了。
http和https区别,https在请求时额外的过程,https是如何保证数据安全的
区别:
HTTP协议传输的数据都是未加密的,即明文,为了保证隐私数据能加密传输,使用SSL协议用于对HTTP协议传输的数据进行加密,这就是HTTPS。简单的说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
- https协议协议到CA申请证书,需要一定的费用
- http是超文本传输协议,信息是明文传输,https则是具有安全性的SSL加密传输协议
- http和https使用的是完全不用的连接方式,用到的端口不同,前者是80,后者是443
- http的连接简单,是无状态的;https协议是ssl+http协议构成的可进行加密传输、身份认证的网络协议,比http协议安全
额外的过程:
https在传输数据之前需要客户端与服务端进行一个握手(TCL/SSL握手),在握手过程中将确立双方加密传输数据的密码信息。TCL/SSL使用了非对称加密,对称加密和hash等。具体过程见的阮一峰先生的博客图解SSL/TLS协议
IP地址子网划分
IP地址的划分:
- A类地址:以0开头,网络号是前一个字节
- B类地址:以10开头,网络号是前两个字节
- C类地址:以110开头,网络号是前三个字节
IP地址由网络号和主机号组成,ip与子网掩码相与得到网络号
子网划分
传统的两级ip地址空间利用率很低,1个A类网络可连接的主机数可超过1000万台,但实际连接数并不多,所以需要对网络进行子网划分,通过子网掩码来区分网络。
三级ip地址:<网络号><子网号><主机号>
TCP如何保证数据的可靠传输的(这个问题可以引申出很多子问题,拥塞控制慢开始、拥塞避免、快重传、滑动窗口协议、停止等待协议、超时重传机制)
总结一:
- 确认和重传:接收方收到报文就会确认,发送方发送一段时间后没有收到确认就会重传
- 数据校验:TCP报文头有校验和,用于校验报文是否损坏
- 数据合理分片和排序:
TCP会按最大传输单元(MTU)合理分片,接收方会缓存为按排序到达的数据,重新排序后交给应用层
UDP:IP数据包大于1500字节,大于MTU。这个时候发送方的IP层就需要分片,吧数据包分成若干片,每一片都小于MTU。而接收方IP层则需要数据包的重组。由于UDP的特性,当某一片数据丢失时,接收方无法重组数据包,导致丢弃整个UDP数据包。 - 流量控制:当接收方来不及处理发送方的数据时,能通过滑动窗口,提示发送方降低发送的速率,防止包丢失。
- 拥塞控制:当网络拥塞时,通过拥塞窗口,减少数据的发送,防止包丢失。
总结二:
- 可靠传输:对于收到的请求,给出确认响应
- 超时重传
- 流量控制:让发送方的发送速率不要太快,要让接收方来得及接受。利用滑动窗口实现流量控制
- 拥塞控制:防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不至过载
- 慢开始:TCP开始发送报文段时先设置拥塞窗口为1
- 拥塞避免:使拥塞窗口按线性规律增长
- 快重传:发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待为其设置的重传计时器到期
- 快恢复(与快重传配合使用):当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把慢开始门限减半。这是为了预防网络发生拥塞。请注意,接下来不执行慢开始算法。
由于发送方现在认为网络很可能没有发生拥塞(如果网络发生了严重的拥塞,就不会一连有好几个报文段连续达到接收方,就不会导致接收方连续发送重复确认),因此与慢开始不同之处是现在不执行慢开始算法(即拥塞窗口现在不设置为1),而是把它设置为慢开始门限减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增长。
长连接与短连接
HTTP协议和TCP协议
HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传输数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致。TCP有可靠,面向连接的特点。
HTTP协议的长连接和短连接
在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器没遇到这样一个Web资源,就会建立一个HTTP会话。
但从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入如下代码:Connection:keep-alive
。在使用长连接的情况下,当一个网页打开完成之后,客户端和服务端之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器的网页,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个事件。实现长连接要客户端和服务端都支持长连接。
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
TCP长连接和短连接
我们模拟一下TCP短连接的情况,client向server发起连接请求,server接到请求,然后双方建立链接。client向server发送消息,server回应client,然后一次读写就完成了,这时候双方任何一个都可以发起close操作,不过一般都是client先发起close操作。为什么呢,一般的server不会回复完client后立即关闭连接的,当然不排除有特殊的情况。从上面的描述看,短连接一般只会在 client/server间传递一次读写操作。
短连接的优点:管理起来比较方便,存在的连接都是有用的连接,不需要额外的控制手段。
我们再模拟一下长连接的情况,client向server发起连接,server接受client连接,双方建立连接。client与server完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个链接。
首先说一下TCP/IP详解上讲到的TCP保活功能,保活功能主要为服务器应用提供,服务器应用希望知道客户主机是否崩溃,从而可以代表客户使用资源。如果客户已经消失,使得服务器上保留一个半开放的连接,而服务器又在等待来自客户端的数据,则服务器将应远等待客户端的数据,保活功能就是试图在服务器端检测到这种半开放的连接。
长连接和短连接的生命周期
短连接在建立连接后,完成一次读写就会自动关闭了。
正常情况下,一条TCP长连接建立后,只要双方不提出关闭请求并且不出现异常情况,这条连接是一直存在的,操作系统不会自动去关闭它,甚至经过物理网络拓扑的改变之后仍然可以使用。所以一条连接保持几天、几个月、几年或者更长时间都有可能,只要不出现异常情况或由用户(应用层)主动关闭。
在编程中,往往需要建立一条TCP连接,并且长时间处于连接状态。所谓的TCP长连接并没有确切的时间限制,而是说这条连接需要的时间比较长。
怎样维护长连接或者检查中断
-
在应用层使用heartbeat来主动监测
对于实时性要求较高的网络通信程序,往往需要更加及时的获取已经中断的连接,从而进行及时的处理。但如果对方的连接异常中断,往往是不能及时的得到对方连接已经中断的信息,操作系统检测连接是否中断的时间间隔默认是比较长的,即便它能够检测到,但却不符合我们的实时性需求,所以需要我们进行手工去不断探测。 -
改变socket的keepalive选项,以使socket检查连接是否中断的时间间隔更小,以满足我们的及时性需求。有关的几个选项使用和解析如下:
-
我们在检测对端以一种非优雅的方式断开连接的时候,可以设置SO_KEEPALIVE属性使得我们在2小时以后发现对方的TCP连接是否依然存在。用法如下:
1
2keepAlive = 1;
setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive)); -
如果我们不想使用这么长的等待时间,可以修改内核关于网络方面的配置参数,也可设置SOCKET的TCP层(SOL_TCP)选项TCP_KEEPIDLE、TCP_KEEPINTVL和TCP_KEEPCNT。
1
2
3TCP_KEEPIDLE:开始首次KeepAlive探测前的TCP空闭时间
TCP_KEEPINTVL:两次KeepAlive探测间的时间间隔
TCP_KEEPCNT:断开前的KeepAlive探测次数如果心搏函数要维护客户端的存活,即服务器必须每隔一段时间必须向客户段发送一定的数据,那么使用SO_KEEPALIVE是有很大的不足的。因为SO_KEEPALIVE选项指"此套接口的任一方向都没有数据交换"。在Linux2.6系列上,上面话的理解是只要打开SO_KEEPALIVE选项的套接口端检测到数据发送或者数据接受就认为是数据交换。因此在这种情况下使用 SO_KEEPALIVE选项。
检测对方是否非正常连接是完全没有作用的,在每隔一段时间发包的情况, keep-alive的包是不可能被发送的。上层程序在非正常断开的情况下是可以正常发送包到缓冲区的。非正常端开的情况是指服务器没有收到"FIN" 或者 "RST"包。
-