详细解释输入网址回车后后台发生的情况。透析HTTP协议与TCP连接之间千丝万缕的关系。为什么要握手三次,挥手四次?time_wait是什么意思?重点问题全面图解,面试再也不用为问这个问题发愁了。一般流程URL解析,解析http协议,端口,资源地址。DNS查询:先查询本地主机,然后访问DNS服务器,将域名解析成ip地址。建立TCP连接。服务器收到请求后进行处理,并构造响应返回给客户端。客户端收到HTTP消息响应。渲染页面,最后可能会挥手四次断开连接,也可能不会,而是重新连接。重点来了:如何理解TCP的三次握手和四次握手?每次握手客户端和服务器的状态是什么?挥手时为什么会出现2MSL,大量Sockets处于TIME_WAIT或CLOSE_WAIT状态时是什么问题?三向握手四次挥手的过程是什么?HTTP报文的格式是什么?URL解析遵循的规则如下:scheme://host.domain:port/path/filename各名词含义解释如下:scheme定义了应用层协议类型,如http、https、ftp等.;host定义域主机(http默认主机为www);domain定义互联网域名,如segmentfault.com;port定义主机的端口,http默认为80,https默认为443;服务器上的路径资源路径;文件名-定义文档/资源的名称;DNS查询浏览器不能直接通过域名找到服务器,只能通过IP地址。那么浏览器是如何通过域名查询到我们输入的url对应的IP呢?浏览器缓存:按照一定的频率缓存DNS数据。操作系统缓存:如果浏览器缓存不错但没有记录,就去操作系统找。RoutingCache:路由器的DNS缓存。ISP的DNS服务器:ISP是InternetServiceProvider(互联网服务提供商)的缩写,ISP有专门的DNS服务器来响应DNS查询请求。根服务器:如果ISP的DNS服务器找不到,就会向根服务器发出请求,进行递归查询(DNS服务器先向根域名服务器询问.com域名服务器的IP地址,然后再询问对于.baidu域名服务器,依次类推)TCP连接建立与断开通过域名解析IP地址后,会建立TCP/IP连接。TCP/IP分为四层,每一层都会加上一个头部,并传送给下一层。到达接收端后,每个对应层解析并拆解对应层的header,抛给上层,与发送端的过程相反。TCP/IP四层模型应用层:发送HTTP请求。浏览器从地址栏获取服务器IP,然后构造一个HTTP报文,其中包括:请求行包含请求方法、URL、协议版本。RequestHeader:由“Keyword:value”对组成,每行一对,keywords和values用英文“:”拆分请求体:请求参数,并不是所有的请求都有请求参数。一般get参数的格式是name=tom&password=1234&realName=tomson,参数也可以放在body中。传输层:一个TCP传输报文在传输报文之前会先建立一个TCP/IP连接,也就是我们后面要讲的三次握手。在这一层,解决了数据的可靠传输、流量控制、拥塞控制等问题。可靠传输对于发送方发送的数据,接收方在收到数据后必须给出确认,以确认自己已经收到数据。如果在规定的时间内没有给出确认,则说明接收方没有收到数据,然后发送方重新发送数据。TCP的可靠传输是通过确认和超时重传机制实现的,而确认和超时重传的具体实现是通过以字节为单位的滑动窗口机制来完成的。TCP拥塞控制TCP协议通过慢启动机制、拥塞避免机制、加速递减机制、快速重传和快速恢复机制共同实现拥塞控制。流控使用通知窗口实现对发送方的流控,通知窗口大小的单位是字节。TCP在TCP数据段头的window字段中填写当前设置的接收窗口(即通知窗口)的大小,告知对方'我们当前的接收窗口大小',实现流量控制。通信双方发送窗口的大小是双方在建立连接时约定好的。在通信过程中,双方可以根据自己的情况动态调整对方发送窗口的大小。网络层:IP协议查询MAC地址打包数据段,并添加源IP地址和目的IP地址,负责寻找传输路径。判断目标地址是否与当前地址在同一网络,如果是,则直接根据Mac地址发送,否则使用路由表寻找下一跳地址,使用ARP协议查询其Mac地址.链路层:以太网协议按照以太网协议将数据以“帧”为单位划分成数据包,每个帧分为两部分:Header:数据包的发送方、接收方和数据类型Data:具体内容数据包的Mac地址以太网规定所有接入网络的设备都必须有一个“网卡”接口,数据包从一个网卡传递到另一个网卡,网卡的地址就是Mac地址。每个Mac地址都是唯一的,并且具有一对一的功能。三向握手需要在传输层传输数据之前建立连接,即三向握手建立可靠连接。三向握手首先要求服务器在建立链接之前监听端口。因此,服务器在建立链接之前的初始状态是LISTEN状态。此时客户端准备建立链接,首先发送一个SYN同步包。发送同步包后,客户端的链接状态变为SYN_SENT状态。服务端收到SYN后同意建立连接,并会回复一个ACK给客户端。由于TCP是双工传输,服务器端也会同时向客户端发送一个SYN,请求服务器端建立到客户端的链接。发送ACK和SYN后,服务器的链接状态变为SYN_RCVD。客户端收到服务器的ACK后,客户端的链路状态变为ESTABLISHED。同时客户端向服务器发送ACK并回复服务器的SYN请求。服务器端收到客户端的ACK后,服务器端的链路状态变为ESTABLISHED状态。此时连接建立完成,双方可以随时传输数据。面试的时候需要明白三次握手是建立双向链接,需要记住client和server之间的链接状态变化。另外,在回答建立连接的问题时,可以提到SYNflood攻击的原因,即服务器收到客户端的SYN请求后,发送ACK和SYN,但客户端没有回复,导致服务器上出现大量链接。SYN_RCVD状态,进而影响其他正常请求的连接建立。可以设置tcp_synack_retries=0来加速半链接的回收,或者增加tcp_max_syn_backlog来应对少量的SYNflood攻击。我们只需要关注80端口和13743端口断开连接的过程,浏览器发送[FIN,ACK]这和网上看到的不一样吗?实际上,客户端在发送[FIN]报文时,会发送一个[ACK]来确认上次发送的确认。然后服务器通过80端口响应[ACK],然后立即响应[FIN,ACK]表示数据传输完成,可以关闭连接了。最后浏览器通过13743端口向服务器发送[ACK]包,客户端与服务器的连接关闭。具体过程如下图抓包所示:四次握手三次握手四次挥手客户端的TCP连接和断开:SYN_SENT-客户端发起第一次握手后,连接状态为SYN_SENT,等待服务器内核响应,如果服务器来不及处理时(例如服务器的积压队列已满),可以看到处于这种状态的连接。ESTABLISHED-表示连接处于健康状态并且可以进行数据传输。客户端收到服务器回复的SYN+ACK后,会单独回复服务器的SYN(第三次握手),连接建立完成,进入ESTABLISHED状态。服务器程序收到第三次握手包后,也进入ESTABLISHED状态。FIN_WAIT_1-客户端发送FIN消息关闭连接后,等待服务器回复ACK确认。FIN_WAIT_2-表示我们已经关闭连接并正在等待服务器关闭。客户端发送FIN报文关闭连接后,服务端发回ACK响应,但并没有关闭,会一直处于这个状态。TIME_WAIT——双方正常关闭连接后,客户端会保持一段时间TIME_WAIT,以保证最后一个ACK能够成功发送给服务端。驻留时间是MSL(maximummessagelifetime)的两倍,在Linux下约为60秒。所以在一个频繁建立短连接的服务器上,通常可以看到上千个TIME_WAIT连接。Server:LISTEN-指示当前程序何时正在侦听某个端口。SYN_RCVD——服务器收到第一次握手后,进入SYN_RCVD状态,并回复SYN+ACK(第二次握手),然后等待对方确认。ESTABLISHED-表示连接处于健康状态并且可以进行数据传输。完成TCP3次握手后,连接建立,进入ESTABLISHED状态。CLOSE_WAIT-表示客户端已经关闭连接,但是本地还没有关闭,正在等待本地关闭。有时客户端程序已经退出,但是服务端程序因为异常或者bug没有调用close()函数关闭连接,那么连接在服务端会一直处于CLOSE_WAIT状态,但是连接并没有存在于客户端。LAST_ACK-表示客户端正在等待服务器关闭请求的最终确认。TIME_WAIT状态存在的原因是着眼于可靠实现TCP全双工连接的终止。在执行关闭连接的四次握手协议时,最后一个ACK由主动关闭端发送。如果最后的ACK丢失了,服务器会重新发送最后的FIN,所以客户端必须维护状态信息以允许它重新发送最后的ACK。如果不维护此状态信息,客户端将响应一个RST小节,服务器会将此小节解释为错误(在java中将抛出连接重置的SocketException)。因此,要实现TCP全双工连接的正常终止,必须处理四段终止序列中任意一段丢失,主动关闭的客户端必须维护状态信息,进入TIME_WAIT状态.允许旧的重复段在网络中消失。由于路由器异常,TCP段可能会“丢失”。在丢失期间,TCP发送方可能会由于确认超时而重发该报文段。路由器修复后丢失的网段也会恢复。发送到最终目的地,这个原始丢失的部分被称为丢失的副本。关闭一个TCP连接后,立即重新建立相同IP地址和端口的TCP连接,后一个连接称为前一个连接的化身,那么可能会出现这种情况,前一个Linkedstrayrepeatgroups出现在前一个链接被断开之后终止,从而被误解为属于新的化身。为了避免这种情况,TCP不允许一个处于TIME_WAIT状态的连接开始新的incarnation,因为TIME_WAIT状态持续2MSL,这样可以保证当一个TCP连接成功建立时,从前一个incarnation中重复的数据包的连接在网络中消失了。另外,在回答断链的问题时,可以提到在实际应用中,可能会有大量的Sockets处于TIME_WAIT或者CLOSE_WAIT状态。一般开启tcp_tw_reuse和tcp_tw_recycle可以加快TIME-WAITSockets的回收;而大量的CLOSE_WAIT可能是被动关闭方的代码bug,没有正确关闭连接。简单的说就是保证TCP协议的全双工连接能够可靠的关闭;确保本次连接的重复数据段从网络中消失,防止端口复用时出现数据混乱;服务器处理请求并响应HTTP报文,深入分析什么是HTTP报文。数据传输通过TCP/IP协议负责底层的传输工作。HTTP协议基本不用管它。所谓的“超文本传输??协议”似乎很少“传输”这件事,那么HTTP的核心是什么呢?TCP报文,在实际要传输的数据之前附加一个20字节的报头数据,存放TCP协议所必需的附加信息,如发送方端口号、接收方端口号、数据包序列号、旗帜等等等。有了这个额外的TCP头,数据包就可以正确传输,到达目的地后去掉头就可以得到真正的数据。这很容易理解。设置起点和终点,针对不同的协议粘贴不同的header,到达对应的目的地时去掉header,提取真正的数据。与TCP/UDP类似,HTTP报文在传输数据之前需要设置一些请求头。不同的是,HTTP是一种“纯文本”协议,所有的头部都是ASCII文本,所以很容易看出是什么。再者,他的请求报文和响应报文的结构基本相同,主要由三部分组成:起始行(StartLine):描述了请求或响应的基本信息。Header:使用key-value的形式详细说明消息信息。空行。消息文本(Entity):需要传输的数据,可以使用图片、视频、文本等。其中,起始行和头字段的前两部分常统称为“请求头”或“响应头”,消息文本也称为“实体”,但对应于“头”,它通常直接称为“身体”。HTTP协议规定报文必须包含头部,后面必须有“空行”,即十六进制的“CRLF”、“0D0A”,不需要“body”。消息结构如下图所示:HTTP消息截取一条消息:透视HTTP协议请求头-起始行请求行由三个字段组成:请求方法字段、URL字段和HTTP协议版本字段,它们之间是分开的按空格。例如,获取/HTTP/1.1。HTTP协议的请求方式有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。GET是请求方式,“/”是请求的目标资源,“HTTP/1.1”是请求协议的版本号。GET/HTTP/1.1翻译成文本大致是:“你好,服务器,我想请求根目录下的默认文件使用HTTP1.1协议版本”。Header的第二部分是Header,由key:value组成。使用自定义标头时的注意事项:标头字段不区分大小写,通常首字母大写;字段名不允许有空格,可以用“-”,不能用“_”;字段名后面必须跟“:”,不能有空格,但“:”后可以有空格。字段名的顺序是没有意义的;浏览器接收响应并呈现数据。一旦接收到响应文本HTML,浏览器渲染机制就开始了。不同浏览器的渲染可能不同,但基本步骤如下:根据HTML解析DOM树;根据CSS解析CSS规则树;结合DOM树和CSS规则树生成渲染树;计算每个节点的信息;根据节点信息,绘制图片显示给用户。本文转载自微信公众号“代码字节”,可通过以下二维码关注。转载本文请联系码哥字节公众号。
