赞
踩
HTTP协议的特点:
(1)HTTP协议是无状态的
就是说每次HTTP请求都是独立的,任何两个请求之间没有什么必然的联系。但是在实际应用当中并不是完全这样的,引入了Cookie和Session机制来关联请求。
(2)多次HTTP请求
在客户端请求网页时多数情况下并不是一次请求就能成功的,服务端首先是响应HTML页面,然后浏览器收到响应之后发现HTML页面还引用了其他的资源,例如,CSS,JS文件,图片等等,还会自动发送HTTP请求这些需要的资源。现在的HTTP版本支持管道机制,可以同时请求和响应多个请求,大大提高了效率。
(3)基于TCP协议
HTTP协议目的是规定客户端和服务端数据传输的格式和数据交互行为,并不负责数据传输的细节。底层是基于TCP实现的。现在使用的版本当中是默认持久连接的,也就是多次HTTP请求使用一个TCP连接。
HTTP报文
HTTP报文分为请求报文和响应报文
报文由三个部分组成,即开始行、首部行和实体主体
(1)请求报文
请求报文的开始行就是请求行,所以请求报文就是由请求行、请求头、内容实体组成的,注意,每一行的末尾都有回车和换行,在内容实体和请求头之间另有一个空行。其中请求行指定的是请求方法、请求URL、协议版本;请求头是键值对的形式存在的,就是字段名:值;内容实体就是要传输的数据。
来自百度首页的请求报文的例子:
请求头中的字段说明:
字段名 | 说明 | 例子 |
---|---|---|
请求方法 | GET | |
HTTP版本号 | HTTP/1.1 | |
Host | 指定请求的服务器的域名和端口号 | Host:www.baidu.com |
Connection | 表示是否需要持久连接(HTTP1.1默认为长连接) | Connection:keep-alive(长连接),close(短连接) |
Cache-Control | 指定请求和响应遵循的缓存机制 | Cache-Control:max-age=0 或者 no-cache |
User-Agent | 发出请求的用户信息(一般是浏览器的信息) | User-Agent: Mozilla/5.0 (Linux; X11) |
Accept | 指定客户端能够接收的内容类型 | Accept:text/html |
Accept-Encoding | 指定浏览器可以支持的web服务器返回内容压缩编码类型 | Accept-Encoding:gzip, deflate, br |
Accept-Language | 浏览器可接受的语言 | Accept-Language:zh-CN,zh |
Cookie | HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器 | Cookie: $Version=1; Skin=new; |
(2)响应报文:
响应报文由状态行、响应首部字段(响应头)、响应实体组成,其中第一行是状态行,依次包含HTTP版本,状态码和状态短语组成;在一个回车换行之后是响应头,也是键值对的形式,字段名:值;然后会有一个空行也包含回车换行,之后是响应实体,就是要传输的数据。
来自百度首页的响应报文的例子
响应头中的字段说明:
字段名 | 说明 | 例子 |
---|---|---|
HTTP版本号 | HTTP/1.1 | |
HTTP状态码 | 200 ok | |
Cache-Control | 告诉所有的缓存机制是否可以缓存那种类型 | Cache-Control:private |
Connection | 表示是否需要持久连接(HTTP1.1默认为长连接) | Connection:keep-alive(长连接),close(短连接) |
Content-Encoding | web服务器支持的返回内容压缩编码类型 | Content-Encoding:gzip |
Date | 原始服务器消息发出的时间 | Date: Sat, 05 Aug 2017 12:26:36 GMT |
Expires | 响应过期的日期和时间 | Expires: Sat, 05 Aug 2017 12:26:49 GMT |
Server | web服务器软件名称 | BWS/1.1 |
Set-Cookie | 设置Http Cookie | Set-Cookie:BDSVRTM=0;path=/ |
Vary | 告诉下游代理是使用缓存响应还是从原始服务器请求 | Vary: Accept-Encoding |
Transfer-Encoding | 文件传输编码 | Transfer-Encoding:chunked |
HTTP请求方法
请求方法是客户端用来告知服务器其动作意图的方法。需要注意的是方法名区分大小写,需要用大写字母。
(1)GET:获取资源
向特定的资源发出请求。注意:GET方法不应当被用来产生“副作用”的操作中,例如在we app中的应用,其中一个原因是GET可能会被爬虫等随意访问。
(2)POST:传输实体主体
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立或对已有资源的修改。POST与GET的区别之一就是目的不同。GET的目的是获取,POST的目的是传输。
(3)PUT:传输主体
PUT方法用来传输文件,向指定资源位置上传其最新内容。类似FTP协议,文件内容包含在请求报文的实体中,然后请求保存到URL指定的服务器位置。
(4)HEAD:获得报文首部
HEAD方法类似GET方法,但是不同的是HEAD方法不要求返回数据(响应体)。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。该方法常用于测试超链接的有效性,是否可以访问,以及最近是否更新等信息。
(5)DELETE:删除文件
DELETE方法用来删除文件,是与PUT相反的方法。DELETE要求服务器删除Request-URI所标识的资源。
(6)OPTIONS:询问支持的方法
因为并不是所有的服务器都支持规定的方法,为了安全有些服务器可能会禁止掉一些方法例如DELETE、PUT等。那么OPTIONS就是用来询问服务器支持的方法。
(7)TRACE:追踪路径
TRACE方法是让Web服务器将之前的请求通信环回给客户端的方法。这个方法并不常用。
(8)CONNECT:要求用隧道协议连接代理
CONNECT方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。主要使用SSL/TLS协议对通信内容加密后传输。
HTTP的响应状态码
状态码是用来告知客户端服务器端处理请求的结果。凭借状态码用户可以知道服务器是请求处理成功、失败或者是被转发;这样出现了错误也好定位。状态码是由3位数字加原因短语组成。3位数字中的第一位是用来指定状态的类别。
共有五种如下:
1xx(Informational,信息性状态码):表示接收的请求正在处理
2xx(Success,成功状态码):表示请求正常处理完毕
3xx(Rediretion,重定向状态码):表示需要客户端进行附加操作
4xx(Client Error,客户端错误状态码):表示客户端的错误,服务器无法处理请求。
5xx(Server Error,服务器错误状态码):表示服务器处理请求出错。
常用的几种HTTP状态码(最常用的8种加粗):
200:请求成功,服务器已成功处理了请求
300:多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301(Moved Permanently,永久移动):请求的资源已被永久地移动到新URL,返回信息会包括新的URL,浏览器会自动定向到新URL,今后任何新的请求都应使用新的URL代替。
302(临时移动):资源只是临时被移动,客户端应继续使用原有URL
400(Bad request):客户端请求的语法错误,服务器无法理解
401(Unauthorized):请求需要有通过HTTP认证的认证信息
403(Forbidden):无权限,服务器拒绝提供服务
404(Not Found):没找到资源
408(Request Timeout):表示客户端请求超时
500(Internal Server error):服务器内部错误
503(Server Unavailable):服务暂不可用,表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
504(Gateway Timeout):网关超时,是代理服务器等待应用服务器响应时的超时。
505(HTTP version not supported):服务器不支持请求的HTTP协议的版本,无法完成处理。
301和302的区别
301:永久性转移,表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址。
302:暂时性转移,表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。
为什么要进行重定向?
(1)网站调整(如改变网页目录结构)
(2)网页被移到一个新地址
(3)网页扩展名改变(如应用需要把.php改为.html或.shtml)
这种情况下,如果不做重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户得到一个404页面操作信息,访问流量白白丧失;再者某些注册了多个域名的网站,也需要通过重定向让访问这些域名的用户自动跳转到主站点等。
应用场景
301比较常用的场景:(1)域名跳转 (2)你把网页的后缀从.php改为.html
(3)把网站从http重定向到https
302比较常用的场景:(1)比如未登陆的用户访问用户中心重定向到登陆页面。
(2)访问404页面会自动重定向到首页。
尽量使用301跳转,原因如下:(网络劫持)
从网址A做一个302重定向到网址B时,主机服务器的隐含意思是网址A随时有可能改主意,重新显示本身的内容或转向其他的地方。大部分的搜索引擎在大部分情况下,当收到302重定向时,一般只要去抓取目标网址就可以了,也就是说网址B。如果搜索引擎在遇到302转向时,百分之百的都抓取目标B的话,就不用担心URL劫持了。
问题就在于,有的搜索引擎,尤其是google,并不能总是抓取目标网址。比如说,有的时候A网址很短,但是它做了一个302重定向到B网址,而B网址是一个很长的乱七八糟的URL网址,甚至还有可能包含一些问号之类的参数。很自然的,A网址更加友好,而B网址既难看又不友好。这是google很有可能会仍然显示网址A。这就造成了网址URL劫持的可能性。
换句话解释一下:
从网站A(网站比较烂)上做了一个302跳转到网站B(搜索排名很靠前),这时候有时搜索引擎会使用网站B的内容,但却收录了网站A的地址,这样在不知不觉中,网站B在为网站A做贡献,网站A的排名就靠前。
目前没有很好的解决网址劫持的方法,只能向google汇报。
重定向的意义?
重定向是为了负载均衡或导入流量,提高SEO排名(搜索引擎排名)。利用一个前端服务器接受请求,然后负载到不同的主机上,可以大大提高站点的业务并发处理能力;重定向也可将多个域名的访问,集中到一个站点;由于baidu.com,www.baidu.com会被搜索引擎认为是两个网站,造成每个的连接数都会减少从而降低排名,永久重定向会将两个地址关联起来,搜索引擎会认为是同一个网站,从而提高排名。
关于HTTP的常见问题及解答
(1)GET和POST的区别
1、GET:从指定的资源请求数据,POST:向指定的资源提交要处理的数据,所以GET用于获取信息而POST是用来更新资源信息
2、GET提交请求的数据实体会放在URL的后面,用?分割,参数用&连接,例如:/index.html?name=li&age=20。POST查询字符串是在POST请求的HTTP消息主体中发送。
3、GET提交的数据长度有限制,因为URL长度有限制,具体的长度限制视浏览器而定,POST对数据长度没有要求。
4、GET提交的数据不安全,因为参数都会暴露在URL上,不应用来处理敏感数据。
5、GET请求可被缓存,可被收藏为书签,GET请求会保留在浏览器历史记录中。
POST请求不会被缓存,不能被收藏为书签,不会保留在浏览器历史记录中。
(2)POST和PUT的区别?
POST方法不是幂等的,PUT方法则有幂等性
幂等:在计算机中,一个幂等操作的特点就是其任意多次执行所产生的影响均与依次一次执行的影响相同。
比如:POST在请求的时候,服务器会每次都创建一个文件,但是在PUT方法的时候只是简单地更新,而不是去重新创建,因此PUT是幂等的。
(3)408 Request Timeout和504 Gateway Timeout的区别?
408是说请求超时,就是建立连接之后在约定的时间内客户端没有发送请求到服务端。本质上原因在于客户端或者网络拥塞。504是网关超时,是说代理服务器把客户端请求转发到应用服务器后在约定的时间内没有收到应用服务器的响应。本质上原因在于服务端的响应过慢,也有可能是网络问题。
(4)Cookie和Session的区别和联系
Cookie和Session都是为了客户端和服务端之间的交互状态,实现机制不同,各有优缺点。首先一个最大的区别就是cookie是保存在客户端而session就保存在服务端的。cookie是客户端请求服务端时服务器会将一些信息以键值对的形式返回给客户端,保存在浏览器中,交互的时候可以加上这些cookie值。用cookie就可以方便的做一些缓存。
cookie的缺点:
(1)大小和数量都有限制。
(2)cookie是存在客户端的,可能被禁用、删除、篡改,是不安全的
(3)cookie如果很大,每次请求都要带上,这样就影响了传输效率
session是基于cookie来实现的,不同的是session本身存在于服务端,但是每次传输的时候不会传输数据,只是把代表一个客户端的唯一ID写在客户端的cookie中,这样每次传输这个ID就可以了。
session的优势:传输数据量小,比较安全
session的缺点:如果session不做特殊的处理容易失效、过期、丢失或者session过多导致服务器内存溢出,并且要实现一个稳定可用安全的分布式session框架也是有一定复杂度的。
cookie和session的区别:
1、Cookie保存在客户端,而Session保存在服务端
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE
4、单个cookie保存的数据不能超过4k(有的说是3K),很多浏览器都限制一个站点最多保存20个cookie
5、将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中
补充:
cookie的内容主要包括:名字、值、过期时间、路径和域。路径与域一起构成cookie的作用范围。若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。这种生命期为浏览器会话期的cookie就称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。若设置了过期时间,浏览器就会把cookie保存在硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的cookie,不同的浏览器有不同的处理方式。
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构来保存信息,当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此sesion相关联的session id, session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。一般这个cookie的名字都是类似于session id。但是cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。
(1)HTTP的URL以http开头,HTTPS的URL以https开头
(2)HTTP是不安全的,而HTTPS是安全的。HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的SSL加密传输协议。HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。
(3)HTTPS协议需要到ca申请证书,HTTP无需证书。一般免费证书很少,需要交费
(4)HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,HTTP标准端口是80,HTTPS标准端口是443。
(5)HTTP的连接很简单,是无状态的。
(6)目前,HTTPS的应用比HTTP的少,是因为HTTPS比较耗性能,对于安全性没那么高要求的应用来说,用HTTP就已经够了。
问题:浏览器如何验证HTTPS证书的合法性?
简单来说是验证两个问题;
(1)证书是否是信任的有效证书。所谓信任,就是指浏览器内置了信任的根证书,就是看看web服务器的证书是不是这些信任根发的或者信任根的二级证书机构颁发的。所谓有效,就是看看web服务器证书是否在有效期,是否被吊销了。
(2)对方是不是上述证书的合法持有者。简单来说证明对方是否持有证书的对应私钥。验证方法两种,一种是对方签个名,我用证书验证签名;另外一种是用证书做个信封,看对方是否能解开。
以上的所有验证,除了验证证书是否吊销需要和CA关联,其他都可以自己完成。验证正式是否吊销可以采用黑名单方式或者OCSP方式。黑名单就是定期从CA下载一个名单列表,里面有吊销的证书序列号,自己在本地比对一下就行。优点是效率高,确定是不实时。OCSP是实时连接CA去验证,优点是实时,缺点是效率不高。
另外一种回答
要想验证证书是否有效,要检查三点
(1)验证证书是否在有效期内
证书中会包含证书的有效期的起始时间和结束时间,取一个时间点去比较就好了。
(2)验证证书是否被吊销了
被吊销的证书是无效的。验证吊销有CRL和OCSP两种方法
CRL即证书吊销列表。证书被吊销后会被记录在CRL中,CA会定期发布CRL。应用程序可以依靠CRL来检查证书是否被吊销了。CRL有两个缺点,一是有可能会很大,下载很麻烦。针对这种情况有增量CRL这种方案。二是有滞后性,就算证书被吊销了,应用也只能等到发布最新的CRL后才能知道。增量CRL也能解决一部分问题,但没有彻底解决。
OCSP是在线证书状态检查协议。应用按照标准发送一个请求,对某张证书进行查询,之后服务器返回证书状态。OCSP可以认为是即时的(实际实现中可能会有一定延迟),所以没有CRL的缺点。不过对于一般的应用来说,实现OCSP还是有些难度的。
(3)验证证书是否是上级CA签发的
每一张证书都是由上级CA证书签发的,上级CA证书可能还有上级,最后会找到根证书。根证书即自签证书,自己签自己。
当你验证一张证书是否是由上级CA证书签发的时候,你必须有这张上级CA证书。通常这张证书会内置在浏览器或者是在操作系统中,有些场景下应用系统也会保留。
以上三点,只要有一个没通过,这张证书就是无效的,不该信任。
一、 ISO七层网络模型
层数 | 名字 | 主要功能 | 对应的典型设备 | 传输单位 |
---|---|---|---|---|
7 | 应用层 | 提供应用程序间通信 | 计算机:应用程序,如FTP、SMTP、HTTP等 | 程序级数据 |
6 | 表示层 | 处理数据格式、数据加密等 | 计算机:编码方式,如图像编解码、URL字段传输编码等 | 程序级数据 |
5 | 会话层 | 建立、维护和管理会话 | 计算机:建立会话,如session认证、断点续传 | 程序级数据 |
4 | 传输层 | 建立主机端到端连接 | 计算机:进程和端口 | 数据段(segment) |
3 | 网络层 | 寻址和路由选择 | 网络:路由器、防火墙、多层交换机 | 数据包(packet) |
2 | 数据链路层 | 提供介质访问、链路管理等 | 网络:网卡、网桥、交换机 | 帧(frame) |
1 | 物理层 | 比特流传输 | 网络:中继器、集线器、网线和HUB | 比特(bit) |
二、五层网络模型
(1)应用层:确定进程之间通信的性质以满足用户需求。应用层协议有很多,如支持万维网应用的HTTP协议,支持电子邮件的SMTP协议,支持文件传送的FTP协议等。
(2)运输层:负责主机间不同进程的通信。这一层中的协议有面向连接的TCP(传输控制协议)、无连接的UDP(用户数据报协议);数据传输的单元称为报文段或用户数据报。
(3)网络层:负责分组交换网中不同主机间的通信。作用:发送数据时,将运输层中的报文段或用户数据报封装成IP数据报,并选择合适路由。
(4)数据链路层:负责将网络层的IP数据报组装成帧。
(5)物理层:透明地传输比特流。
三、TCP/IP分层模型(四层)
(1)应用层
对应于OSI七层模型的应用层和表示层。因特网的应用层协议包括:FTP(文件传输协议)、HTTP(超文本传输协议)、Telent(远程终端协议)、SMTP(简单邮件传送协议)等。
(2)传输层
对应于OSI七层模型的传输层,提供两种端到端的通信服务。其中TCP协议提供可靠的数据流运输服务,UDP协议提供不可靠的用户数据报服务。
(3)网间层
对应于OSI七层模型的网络层。本层包括IP协议、RIP协议,负责数据的包装、寻址和路由。同时还包含ICMP(网间控制报文协议)用来提供网络诊断信息。
(4)网络接口层
提供TCP/IP协议的数据结构和实际物理硬件之间的接口。
类型 | TCP | UDP |
---|---|---|
可靠性 | 可靠 | 不可靠 |
连接性 | 面向连接 | 无连接 |
报文 | 面向字节流 | 面向报文(保留报文的边界) |
效率 | 传输效率低 | 传输效率高 |
双工性 | 全双工(点到点) | 一对一、一对多、多对一、多对多 |
流量控制 | 有(滑动窗口) | 无 |
拥塞控制 | 有(慢开始、拥塞避免、快重传、快恢复) | 无 |
同步/异步主要针对client端(客户端),阻塞/非阻塞主要针对server端(服务器端)
同步:发送方发出数据后,等待接收方发回响应以后才发下一个数据包的通讯方式。
异步:发送方发出数据后,不等待接收方发回响应,接着发送下个数据包的通讯方式。
阻塞调用:是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。
非阻塞调用:指在不能立即得到结果之前,该函数不会阻塞当前线程,而会立即返回。
HTTP的长连接和短连接本质上是TCP的长连接和短连接
短连接:一般只会在client/server间传递一次读写操作,就断开连接
长连接:在client/server完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。
在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就终端连接。如果客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话。
但从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入代码:Connection:keep-alive
第一步:解析域名,找到主机IP
(1)先从浏览器缓存中找,如果有缓存,直接返回IP,否则下一步
(2)缓存中无法找到IP,浏览器会进行一个系统调用,查询hosts文件。如果找到,直接返回IP,否则下一步。(在计算机本地目录etc下有一个hosts文件,hosts文件中保存有域名与IP的对应解析,通常也可以修改hosts科学上网或破解软件)
(3)当(1)(2)查询均无果,只能借助于网络。路由器一般都会有自己的DNS缓存,ISP服务商DNS缓存,这是一般都能够得到相应的IP。如果还是无果,只能借助于DNS递归解析。
(4)这是,ISP的DNS服务器就会开始从根域名服务器开始递归搜索,从.com顶级域名服务器,到baidu的域名服务器。
总结:浏览器缓存->系统hosts文件->路由器DNS缓存、ISP服务商DNS缓存->递归搜索(从.com根域名服务器到baidu的域名服务器)
第二步:浏览器与网站建立TCP连接
浏览器利用IP直接与网站主机通信,通过三次握手,TCP连接建立完成
第三步:浏览器发起GET请求
浏览器向主机发起一个HTTP-GET方法报文请求。请求中包含访问的URL,也就是http://www.baidu.com/,还有User-Agent用户浏览器操作系统信息,编码等。注意:Accept-Encoding和cookies项,Accept-Encoding一般采用gzip,压缩之后传输html文件。cookies如果是首次访问,会提示服务器建立用户缓存信息,如不是,可以利用cookies对应键值,找到相应缓存,缓存里面存放着用户名,密码和一些用户设置项。
第四步:显示页面或返回其他
返回状态码200ok,表示服务器可以处理请求,返回报文,由于在报头中,content-type为“text/html”,浏览器以html形式呈现,而不是下载文件。
对于大型网站存在多个主机站点,往往不会直接返回请求页面,而是重定向。返回的状态码就不是200ok,而是301,302以3开头的重定向码,浏览器在获取了重定向响应后,在响应报文中location项找到重定向地址,浏览器重新第一步访问即可。
TCP首部的前20个字节是固定的,后面有可能还有4N字节的选项(根据需要而增加)。因此TCP首部最小长度是20个字节。
(1)每个TCP链接都包括源端与目的端的端口号,各占2个字节,这两个值加上IP首部中源端IP地址与目的端IP地址构成一个TCP连接
(2)序号,无符号数,占4个字节。是用来标识从发端向收端发送的数据字节流。TCP是面向字节流的,它所传送的字节流中的每个字节都按顺序编号,整个要传送的字节流的起始序号是在建立连接时设置。而首部中的序号字段值是本报文段所发送的数据的第一个字节的序号。
(3)确认号,也占4个字节,是期望收到的对方下一个报文段的第一个数据字节的序号。
只有ACK的标志为1时,确认序号字段才有效,发送该字段无任何代价,因为确认序号与ACK标志一样总是TCP首部的一部分。因此当一个连接被建立之后,这个字段总是被设置,ACK标志也总是被置为1。
(4)数据偏移,占4位(注意是位不是字节),它指出TCP报文段数据部分距报文段的起始部分有多远。也就是指出TCP报文段首部的长度。
(5)保留,占6位,保留为今后使用。
下面要讲述非常重要的六个控制字段,这六个字段各占一位。
(6)紧急URG(URGent):当URG=1时,表明“紧急指针”字段有效。它告诉系统此报文段中有紧急数据,应当尽快传送,而不要按原来的排除顺序进行传送。当你用网络程序传送数据时,忽然发现了一些问题,想取消该程序的运行,发出中断命令,这时就可以使用紧急数据,如果不这样,控制命令字符就处于TCP缓存末尾,只有在所有数据处理完毕之后,这个控制命令字符才会被交付到接收方的应用进程,这样就浪费了许多时间。
(7)确认ACK(ACKnowlegment):当ACK=1时,“确认”字段才有效,TCP规定,在连接建立后,所有传送的报文段,都必须报文段置1。
(8)推送PSH(PuSH):这个很少使用。
(9)复位RST(ReSet):当RST=1表明,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接。RST置1用来拒绝一个非法的报文段(例如客户端在没有发送SYN报文的情况下,忽然发送一个ACk包,服务端自然会回应一RST报文进行拒绝),或拒绝打开一个连接。因此RST位也叫做重置位或重建位。
(10)同步SYN(SYNchronization):在建立连接时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段;对方若同意建立连接,则在响应的报文段使用SYN=1并且ACK=1。因此当SYN=1时,表明这是一个连接请求或连接接受报文。关于TCP的连接的建立与释放请看:Tcp协议怎样建立主机之间连接——“三次握手”
(11)终止FIN(FiNis):用来释放一个连接,当FIN=1时,表示此报文段发送方的数据已发送完毕,并要求释放连。
(12)窗口大小:占2个字节,窗口值范围是[0, 2的16次方-1]。窗口指的是发送报文段的一方的接收窗口(并非自己的发送窗口)。窗口值告诉对方:从本报文段首部中的确认号算起,接收目前允许对方发送的数据量。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。窗口值将作为接收方让发送方设置其发送窗口的依据。窗口值是经常在变化着的。
(13)检验和:占2个字节,该字段检验的范围包括报文段的首部和数据两个部分。
(14)紧急指针:占2个字节,只有当URG=1时,这个字段才有效。它指出本报文段中紧急数据的字节数,而紧急数据结束后就是普通数据。当所有紧急数据都处理完成时,TCP就告诉应用程序恢复到正常操作。
值得注意的是,即使窗口为0也可以发送紧急数据。
(15)选项:长度可变,最长可以达40个字节。当没有使用选项时,首部的长度为20个字节。
最初TCP只规定了一种选项即最大报文段长度MSS(Maximum Segment Size),它指的是报文段中数据部分的长度。后来又陆续增加了“窗口扩大”选项、“时间戳”选项及有关“选择确认(SACK)”选项。
过程图如下:
TCP状态转换图
上半部分是TCP三次握手过程的状态变迁
1、SYN_SENT:第一次握手发生阶段,客户端发起连接。客户端调用connect,发送SYN给服务器端,然后进入SYN_SENT状态,等待服务器端确认(三次握手中的第二个报文)。如果服务器端不能连接,则直接进入CLOSED状态。
2、LISTEN:服务器端等待连接的状态。服务器端经过socket, bind, listen函数之后进入此状态,开始监听客户端发过来的连接请求。此称为应用程序被动打开(等到客户端连接请求)。
3、SYN_RCVD:第二次握手发生阶段,这里是服务器端接收到了客户端的SYN,此时服务器由LISTEN进入SYN_RCVD状态,同时服务器端回应一个ACK,然后再发送一个SYN即SYN+ACK给客户端。
4、ESTABLISHED:第三次握手发生阶段,客户端接收到服务器端的ACK包(ACK、SYN)之后,也会发送一个ACK确认包,客户端进入ESTABLISHED状态,表明客户端这边已经准备好,但TCP需要两端都准备好才可以进行数据传输。服务器端收到客户端的ACK之后会从SYN_RCVD状态转移到ESTABLISHED状态,表明服务器端也准备好进行数据传输了。这样客户端和服务器端都是ESTABLISHED状态,就可以进行后面的数据传输了。所以ESTABLISHED也可以说是一个数据传送状态。
四次挥手过程的状态变迁
1、FIN_WAIT_1:第一次挥手,主动关闭的一方(执行主动关闭的一方既可以是客户端,也可以是服务器端,这里以客户端执行主动关闭为例),终止连接时,发送FIN给对方,然后等待对方返回ACK。调用close()第一次挥手就进入此状态。
2、CLOSE_WAIT:接收到FIN之后,被动关闭的一方进入此状态。具体动作是接收到FIN,同时发送ACK。之所以叫CLOSE_WAIT可以理解为被动关闭的一方此时正在等待上层应用程序发出关闭连接指令。因为TCP关闭是全双工过程,这里客户端执行了主动关闭,被动方服务器端接收到FIN后也需要调用close关闭,这个CLOSE_WAIT就是处于这个状态,等待发送FIN,发送了FIN则进入LAST_ACK状态。
3、FIN_WAIT_2:主动端(这里是客户端)先执行主动关闭发送FIN,然后接收到被动方返回的ACK后进入此状态。
4、LAST_ACK:被动方(服务器端)发起关闭请求,由状态2进入此状态,具体动作是发送FIN给对方,同时在接收到ACK时进入CLOSED状态。
5、CLOSING:两边同时发起关闭请求时(即主动方发送FIN,等待被动方返回ACK,同时被动方也发送了FIN,主动方接收到了FIN之后,发送ACK给被动方),主动方会由FIN_WAIT_1进入此状态,等待被动方返回ACK。
6、TIME_WAIT:四次挥手操作最后都会经过这样一个状态然后进入CLOSED状态。共有三个状态会进入此状态
(1)由CLOSING进入:同时发起关闭情况下,当主动端接收到ACK后,进入此状态,实际上这里的同时是这样的情况:客户端发起关闭请求,发送FIN之后等待服务器端回应ACK,但此时服务器端同时也发起关闭请求,也发送了FIN,并且被客户端先于ACK接收到。
(2)由FIN_WAIT_1进入:发起关闭后,发送了FIN,等待ACK的时候,正好被动方也发起关闭请求,发送了FIN,这是客户端接收到了先前ACK,也收到了对方的FIN(即ACK和FIN同时收到),然后发送ACK,进入TIME_WAIT状态(这里跳过了FIN_WAIT_2状态)
(3)由FIN_WAIT_2进入
问题:TIME_WAIT等待两个MSL作用?
可靠安全的关闭TCP连接。比如网络拥塞,主动方最后一个ACK被动方没收到,这时被动方会对FIN开启TCP重传,发送多个FIN包,在TCP/IP协议就是这样设计的,是不可避免的。主要有两个原因:
(1)网络情况不好时,如果主动方无TIME_WAIT等待,关闭前个连接后,主动方与被动方又建立起新的TCP连接,这时被动方重传或延时过来的FIN包过来后会直接影响新的TCP连接。
(2)同样网络情况不好并且无TIME_WAIT等待,关闭连接后无新连接,当接收到被动方重传或延迟的FIN包后,会给被动方回一个RST包,可能会影响被动方其他的服务连接。
RST包:用于强制关闭TCP连接
RST标示复位、用来异常的关闭连接。
1. 发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓冲区中的包,发送RST。
2. 而接收端收到RST包后,也不必发送ACK包来确认。
什么时候发送RST包?
1. 建立连接的SYN到达某端口,但是该端口上没有正在 监听的服务。
2. TCP收到了一个根本不存在的连接上的分节。
3. 请求超时。 使用setsockopt的SO_RCVTIMEO选项设置recv的超时时间。接收数据超时时,会发送RST包。
TIME_WAIT状态维持时间是两个MSL时间长度,也就是在1-4分钟,windows操作系统就是4分钟。
MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间IP数据包将在网络中消失。
问题:4、客户端收到一个窗口为 0 的包怎么处理?
有这样一个问题:考虑这样一种特殊情况,就是接收方若没有足够的缓存使用,就会发送零窗口大小的报文,此时发送方将发送窗口设置为0,停止发送数据,之后接收方有足够的缓存,发送了非零窗口大小的报文,但是这个报文在中途丢失了,那么发送方的发送窗口就一直为零导致死锁。
解决这个问题:TCP为每个连接设置一个持续计时器,只要TCP的一方收到对方的零窗口通知。就启动该计时器,周期性的发送一个零窗口探测报文段(仅携带1字节的数据)。对方就在确认这个报文的时候给出现在的窗口大小。(注:TCP规定,即使设置为零窗口,也必须接收以下几种报文段,零窗口探测报文段,确认报文段和携带紧急数据的报文段)。
DNS(Domain Name System的缩写)域名系统,主要提供网站域名与IP地址的相互转化的服务,就是根据域名查出IP地址。你可以把它想象成一本巨大的电话本。
具体来说,如果你要访问域名www.baidu.com,首先要通过DNS查出它的IP地址是xx.xx.xx.xx。
域名解析时使用UDP协议
客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过TCP三次握手,这样DNS服务器负载更低,响应更快。虽然从理论上说,客户端也可以指定向DNS服务器查询的时候使用TCP,但事实上,很多DNS服务器进行配置的时候,仅支持UDP查询包。
DNS服务的工作过程:
当DNS客户机需要查询程序中使用的名称时,它会查询本地DNS服务器来解析该名称。客户机发送的每条查询消息都包括3条信息,以指定服务器应回答的问题。
(1)指定的DNS域名,表示为完全合格的域名(FQDN)
(2)指定的查询类型,它可根据类型指定资源记录,或作为查询操作的专门类型。
(3)DNS域名的指定类别
对于DNS服务器,它始终应指定为internet类别。
TCP协议如何保证可靠传输:
(1)确认和重传:接收方收到报文就会确认,发送方发送一段时间后没有收到确认就重传
三种协议:停-等协议,后退N帧协议,选择重传协议
(2)数据校验—TCP头部字段:校验和
验证的方法:将校验和与要校验的字段相加,结果为0就是正确的
(3)数据合理分片和排序
UDP:IP数据报大于1500字节,大于MTU。这个时候发送方IP层就需要分片。把数据报分成若干片,使每一片都小于MTU。而接收方IP层则需要进行数据报的重组。这样就会多做许多事情,而更严重的是,由于UDP的特性,当某一片数据传送中丢失时,接收方便无法重组数据报。将导致丢弃整个UDP数据报。
TCP会按MTU合理分片,接收方会缓存未按序到达的数据,重新排序后再交给应用层。
(4)流量控制:当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。
所以如果窗口值为0,发送端就会开启一个持续计数器,每个一段时间询问一下接收方。
(5)拥塞控制:当网络拥塞时,减少数据的发送。
慢开始、拥塞避免、快重传、快恢复
多路IO复用,有时也称为事件驱动IO,基本原理就是有个函数(如select)会不断地轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。
select、poll和epoll都是多路IO复用的机制。多路IO复用就通过一种机制,可以监视多个描述符,一旦某个描述符(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select、poll和epoll本质上都是同步IO,因为它们都需要在读写时间就绪后自己负责进行读写,即是阻塞的,而异步IO则无须自己负责进行读写,异步IO的实现会负责把数据从内核拷贝到用户空间。
select和poll比较:
一般认为poll()比select()要高级一些,主要源于以下几个原因:
(1)poll()不要求开发者在计算最大文件描述符时进行+1的操作
(2)poll()在应付大数目的文件描述符的时候速度更快,因为对于select()来说内核需要检查大量描述符对应的fd_set中的每一个比特位,比较费时。
(3)select()可以监控的文件描述符数目是固定的,相对来说也较少(1024或2048)。如果需要监控数值比较大的文件描述符,或是分布得很稀疏的较少的描述符,效率也会很低。而对于poll()函数来说,就可以创建特定大小的数组来保存监控的描述符,而不受文件描述符值大小的影响,而且poll()可以监控的文件数目远大于select()
(4)对于select()来说,所监控的fd_set在select()返回之后会发生变化,所以在下一次进入select()之前都需要重新初始化需要监控的fd_set,poll()函数将监控的输入和输出事件分开,允许被监控的文件数组被复用而不需要重新初始化。
(5)select()函数的超时参数在返回时也是未定义的,考虑到可移植性,每次在超时之后在下一次进入到select()之前都需要重新设置超时参数。
fd_set可以理解为一个集合,这个集合中存放的是文件描述符(file descriptor),即文件句柄,这可以认为是常说的普通意义的文件。
select()的优点:
(1)select()的可移植性更好,在某些UNIX系统上不支持poll()
(2)select()对于超时值提供了更好的精度,而poll()是精度较差
epoll的优点:
(1)支持一个进程打开大数目的socket描述符(FD)
(2)IO效率不随FD数目增加而线性下降
传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合,不过由于网络延迟,任一时间只有部分的socket是“活跃”的,但是select/poll每次调用都会线性扫描全部的结合,导致效率呈现线性下降。但是epoll不会存在这个问题,它只会对“活跃”的socket进行操作,这是因为在内核中实现epoll是根据每个fd上面的callback函数实现的。那么只有“活跃”的socket才会主动去调用callback函数,其他idle状态socket则不会,在这点上,epoll实现了一个“伪”AIO,因为这时候推动力由Linux内核提供。
(3)使用mmap加速内核与用户空间的消息传递。
问题:epoll 水平触发和边缘触发是什么?
Level_triggered(水平触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据一次性全部读写完(如读写缓冲区太小),那么下次调用 epoll_wait()时,它还会通知你在上没读写完的文件描述符上继续读写,当然如果你一直不去读写,它会一直通知你!!!如果系统中有大量你不需要读写的就绪文件描述符,而它们每次都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率!!!
Edge_triggered(边缘触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太小),那么下次调用epoll_wait()时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你!!!这种模式比水平触发效率高,系统不会充斥大量你不关心的就绪文件描述符!!!
版权声明:本文为博主原创文章,转载请标明原文地址,谢谢 ^_^ https://blog.csdn.net/xiaoquantouer/article/details/76762131
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。