目录

http的连接:

http报文格式:

http请求方法

cookie和session

referer:

长连接和短连接

http状态码

https建立连接的过程:

http缓存

1. 优点

2. 实现方法

3. Cache-Control

4. 缓存验证

DNS

那么我们的DNS是怎么解析一个域名的呢?

HTTP协议与内容压缩:

http协议的发展过程

tcp连接过程与三次握手

Time_wait

Content-Type

Content-Type的格式:

常见Content-Type

网络基础知识理解:

1.数据链路层:

2.网络层

3.运输层

滑动窗口:

流量控制

拥塞控制:


本部分为学习《图解http》的笔记

http版本:0.9    -   1.0   -   1.1   -   2

http的连接:

http  request是没有连接这个概念的,他只有发送接收数据请求的操作,因此是基于tcp建立好连接的基础上才能进行请求。

短连接:http1.0,每次请求之前建立tcp连接,请求完成后关闭tcp连接

长连接:http1.1,每次请求之前建立tcp连接,请求完成后保持tcp连接

tcp三次握手是有一定开销的

url: uniform resource locator 统一资源定位器

http报文格式:

一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成,下图给出了请求报文的一般格式。

<request-line>
<headers>
<blank line>                    即\r\n
[<request-body>

如:

即       

请求报文:

如    GET /index.htm HTTP/1.1
        Host: hackr.jp

起始行开头的GET表示请求访问服务器的类型,称为方法(method)。随后的字符串 /index.htm 指明了请求访问的资源对象,
也叫做请求 URI(request-URI)。最后的 HTTP/1.1,即 HTTP 的版本号,用来提示客户端使用的 HTTP 协议功能。综合来看,这段请求内容的意思是:请求访问某台 HTTP 服务器上的/index.htm 页面资源。请求报文是由请求方法、请求 URI、协议版本、可选的请求首部字段和内容实体构成的。

响应报文:

在起始行开头的 HTTP/1.1 表示服务器对应的 HTTP 版本。紧挨着的 200 OK 表示请求的处理结果的状态码(status code)和原因短语(reason-phrase)。下一行显示了创建响应的日期时间,是首部字段(header field)内的一个属性。接着以一空行分隔,之后的内容称为资源实体的主体(entity body)。

http请求方法

GET获取资源GET 方法用来请求访问已被 URI 识别的资源。指定的资源经服务器端解析后返回响应内容。也就是说,如果请              求的资源是文本,那就保持原样返回;如果是像 CGI(Common Gateway Interface,通用网关接口)那样的程序,则返              回经过执行后的输出结果。

POST:传输实体主体(比如网上发帖)

POST 方法用来传输实体的主体。虽然用 GET 方法也可以传输实体的主体,但一般不用 GET 方法进行
             传输,而是用 POST 方法。虽说 POST 的功能与 GET 很相似,但POST 的主要目的并不是获取响应的主体内容。

例子:

POST /0523/index.php HTTP/1.1
Host: liangyue.net.cn
Content-type: application/x-www-form-urlencoded
Content-length: 45tit=word&con=76549&submit=%E7%95%99%E8%A8%80

其中,requestbody的内容应该符合网站的格式要求

get和post的区别:

1.最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。

2.GET请求在URL中传送的参数是有长度限制的,而POST没有。(大多数)浏览器通常都会限制url长度在2K个字节

3.GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。客户端把用户 ID 和密码等登录信息放入                                              报 文的实体部分,通常是以 POST 方法把请求发送给服务器。

4.

后退按钮/刷新 GET无害 POST数据会被重新提交(浏览器应该告知用户数据会被重新提交)。

5.GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

6.GET和POST还有一个重大区别,简单的说:GET产生一个TCP数据包;POST产生两个TCP数据包。

长的说:

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)

HTTP请求,最初设定了八种方法。这八种方法本质上没有任何区别。只是让请求,更加有语义而已。

HTTP给汽车运输设定了好几个服务类别,有GET, POST, PUT, DELETE等等,HTTP规定,当执行GET请求的时候,要给汽车贴上GET的标签(设置method为GET),而且要求把传送的数据放在车顶上(url中)以方便记录。如果是POST请求,就要在车上贴上POST的标签,并把货物放在车厢里。当然,你也可以在GET的时候往车厢内偷偷藏点货物,但是这是很不光彩;也可以在POST的时候在车顶上也放一些数据,让人觉得傻乎乎的。HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。

PUT:传输文件
         PUT 方法用来传输文件。就像 FTP 协议的文件上传一样,要求在请求报文的主体中包含文件内容,然后保存到请求 URI 指定的位置。但是,鉴于 HTTP/1.1 的 PUT 方法自身不带验证机制,任何人都可以上传文件 , 存在安全性问题,因此一般的 Web 网站不使用该方法。若配合 Web 应用程序的验证机制,或架构设计采用REST(REpresentational State Transfer,表征状态转移)标准的同类Web 网站,就可能会开放使用 PUT 方法。

HEAD:获得报文首部
            HEAD 方法和 GET 方法一样,只是不返回报文主体部分。用于确认URI 的有效性及资源更新的日期时间等。

比如我们只想要确定网站是否还正常运行,或者某资源是否还存在,而不需要得到资源中的内容,那么可以用HEAD,如

HEAD / HTTP/1.1
Host: www.zixue.it

DELETE:删除文件
      DELETE 方法用来删除文件,是与 PUT 相反的方法。DELETE 方法按请求 URI 删除指定的资源。但是,HTTP/1.1 的 DELETE 方法本身和 PUT 方法一样不带验证机制,所以一般的 Web 网站也不使用 DELETE 方法。当配合 Web 应用程序的验证机制,或遵守 REST 标准时还是有可能会开放使用的。

OPTIONS:询问支持的方法,返回服务器可用的请求方法
           OPTIONS 方法用来查询针对请求 URI 指定的资源支持的方法。

TRACE:追踪路径
TRACE 方法是让 Web 服务器端将之前的请求通信环回给客户端的方法。(比如用了代理访问了百度,现在想看看代理是否对我的http请求进行了篡改,可以用TRACE看看服务器上回收到的请求内容)

CONNECT:要求用隧道协议连接代理
CONNECT 方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行 TCP 通信。主要使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加 密后经网络隧道传输。

CONNECT 方法的格式如下所示。
                   CONNECT 代理服务器名:端口号 HTTP版本

cookie和session

让我们用几个例子来描述一下cookie和session机制之间的区别与联系。笔者曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微乎其微,这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案:
1、该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。
2、发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。      --cookie
3、发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。--session

1.cookie:保存在客户端,请求时一并发给服务器,来确认(如上次登录的)状态

HTTP 是一种不保存状态,即无状态(stateless)协议。HTTP 协议自身不对请求和响应之间的通信状态进行保存。

可是,随着 Web 的不断发展,因无状态而导致业务处理变得棘手的情况增多了。比如,用户登录到一家购物网站,即使他跳转到该站的其他页面后,也需要能继续保持登录状态。针对这个实例,网站为了能够掌握是谁送出的请求,需要保存用户的状态。

HTTP/1.1 虽然是无状态协议,但为了实现期望的保持状态功能,于是引入了 Cookie 技术。有了 Cookie 再用 HTTP 协议通信,就可以管理状态了

不可否认,无状态协议当然也有它的优点。由于不必保存状态,自然可减少服务器的 CPU 及内存资源的消耗。从另一侧面来说,也正是因为 HTTP 协议本身是非常简单的,所以才会被应用在各种场景里。

保留无状态协议这个特征的同时又要解决类似的矛盾问题,于是引入了 Cookie 技术。Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息,通知客户端保存 Cookie。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入 Cookie 值后发送出去。服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录(session-id),最后得到之前的状态信息。

2.session

session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
 
当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识- 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。 保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID,而。比如weblogic对于web应用程序生成的cookie,JSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是JSESSIONID。
 
由于cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面,附加方式也有两种,一种是作为URL路径的附加信息,表现形式为http://...../xxx;jsessionid=ByOK ... 99zWpBng!-145788764
另一种是作为查询字符串附加在URL后面,表现形式为http://...../xxx?jsessionid=ByOK ... 99zWpBng!-145788764
这两种方式对于用户来说是没有区别的,只是服务器在解析的时候处理的方式不同,采用第一种方式也有利于把session id的信息和正常程序参数区分开来。
为了在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。
在谈论session机制的时候,常常听到这样一种误解“只要关闭浏览器,session就消失了”。其实可以想象一下会员卡的例子,除非顾客主动对店家提出销卡,否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的,除非程序通知服务器删除一个session,否则服务器会一直保留,程序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个session id就消失了,再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的session id发送给服务器,则再次打开浏览器仍然能够找到原来的session。在服务端保存Session的方法很多,内存、数据库、文件都有。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。

恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。

总结:服务器客户端如何对一个session进行维护:

当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识- 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id。第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了 Cookie 怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。

恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。

cookie值的设置,往往还与当前header、reference等字段值有关,这是为了防止别人伪造cookie身份进行登录

在http头信息里,有一个重要的选项:referer

referer:

代表着网页的来源,即上一页的地址

如果直接输入网址进来,就不会有referer头,这也是为什么服务器知道客户哈哈是从那个网址的链接点进来的

应用问题:如何配置apache服务器,用于图片防盗链?

原理:在web服务器层面,根据http协议的referer头信息来判断,如果来自站外,则统一url重写到一个很小的防盗链提醒图片上去。

长连接和短连接

HTTP 协议的初始版本中,每进行一次 HTTP 通信就要断开一次 TCP连接。

以当年的通信情况来说,因为都是些容量很小的文本传输,所以即使这样也没有多大问题。可随着 HTTP 的普及,文档中包含大量图片的情况多了起来。

为解决上述 TCP 连接的问题,HTTP/1.1 和一部分的 HTTP/1.0 想出了持久连接(HTTP Persistent Connections,也称为 HTTP keep-alive 或HTTP connection reuse)的方法。持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。

持久连接的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。另外,减少开销的那部分时间,使HTTP 请求和响应能够更早地结束,这样 Web 页面的显示速度也就相应提高了。在 HTTP/1.1 中,所有的连接默认都是持久连接,但在 HTTP/1.0 内并未标准化。虽然有一部分服务器通过非标准的手段实现了持久连接,但服务器端不一定能够支持持久连接。毫无疑问,除了服务器端,客户端也需要支持持久连接。

HTTP/1.1 之前的 HTTP 版本的默认连接都是非持久连接。为此,如果想在旧版本的 HTTP 协议上维持持续连接,则需要指定
Connection 首部字段的值为 Keep-Alive。如上图①所示,客户端发送请求给服务器时,服务器端会像上图②那样加上首部字段 Keep-Alive 及首部字段 Connection 后返回响应。

管线化
持久连接使得多数请求以管线化(pipelining)方式发送成为可能。从前发送请求后需等待并收到响应,才能发送下一个请求。管线化技术出现后,不用等待响应亦可直接发送下一个请求。这样就能够做到同时并行发送多个请求,而不需要一个接一个地等待
响应了。

因为我们请求网站的页面时往往要发送多个http请求,包括文字、图片、视频等请求,如果每次都要等到上一个请求处理完再发送下一个请求,那么就会大大降低效率。

http状态码

状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果。借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了错误。

常用:

100——客户必须继续发出请求

101——客户要求服务器根据请求转换HTTP协议版本

200 OK 请求在服务器端被正常处理

204 No Content 服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分,即没有资源返回,浏览器页面不更新

206 Partial Content 该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的GET 请求。响应报文中包含由Content-Range 指定范围的实体内容

301 Moved Permanently 永久性重定向。该状态码表示请求的资源已被分配了新的 URI,以后应使用资源现在所指的 URI(应更改浏览器书签)。

302 Found 临时性重定向。该状态码表示请求的资源已被分配了新的 URI,希望用户(本次)能使用新的 URI 访问。

303 See Other 该状态码表示由于请求对应的资源存在着另一个 URI,应使用 GET方法定向获取请求的资源。303 状态码和 302 Found 状态码有着相同的功能,但 303 状态码明确表示客户端应当采用 GET 方法获取资源,这点与 302 状态   码有区别。

304 not modified 服务器上此资源未修改,你从本地缓存中取就行

400 Bad Request 该状态码表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。另外,浏览器会像 200 OK 一样对待该状态码。

401 Unauthorized 该状态码表示发送的请求需要有通过 HTTP 认证(BASIC 认证、DIGEST 认证)的认证信息。另外若之前已进行过 1 次请求,则表示用 户认证失败。

403 Forbidden 该状态码表明对请求资源的访问被服务器拒绝了。服务器端没有必要给出拒绝的详细理由,但如果想作说明的话,可以在实体的主体部分对原因进行描述,这样就能让用户看到了。

404 Not Found 该状态码表明服务器上无法找到请求的资源。除此之外,也可以在服务器端拒绝请求且不想说明理由时使用。

5XX 的响应结果表明服务器本身发生错误。

500 Internal Server Error 该状态码表明服务器端在执行请求时发生了错误。也有可能是 Web应用存在的 bug 或某些临时的故障。

503 Service Unavailable 该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。如果事先得知解除以上状况需要的时间,最好写入RetryAfter 首部字段再返回给客户端

https建立连接的过程:

完整过程:

step1: “客户”向服务端发送一个通信请求

“客户”->“服务器”:你好,这是我支持的加密协议及版本。SSL、TLS。把自身支持的一系列Cipher Suite(密钥算法套件,简称Cipher)(自己支持的一套加密算法和哈希算法)发送给服务端

step2: “服务器”向客户发送自己的数字证书。证书中有一个公钥用来加密信息,私钥由“服务器”持有

“服务器”->“客户”:你好,我是服务器,这里是我的数字证书、支持的SSL、TLS。

step3: “客户”收到“服务器”的证书后,它会去验证这个数字证书到底是不是“服务器”的,数字证书有没有什么问题,数字证书如果检查没有问题,就说明数字证书中的公钥确实是“服务器”的。(如该网站证书已过期,该网站证书不安全)

step4:如果证书验证通过,或者用户接受了不受信任证书,“客户”生成一个对称加密算法和密钥,用于后面的通信的加密和解密。这个对称加密算法和密钥,“客户”会用公钥加密后发送给“服务器”,别人截获了也没用,因为只有“服务器”手中有可以解密的私钥。这样,后面“服务器”和“客户”就都可以用对称加密算法来加密和解密通信内容了。

客户端生成随机字符串作为对称密钥后,还会涉及到下面这个流程:

--------------------------------------------------------------------

HASH握手信息:用最开始约定好的HASH方式,把握手消息取HASH值, 然后用 随机数加密 “握手消息+握手消息HASH值(签名)” 并一起发送给服务端
在这里之所以要取握手消息的HASH值,主要是把握手消息做一个签名,用于验证握手消息在传输过程中没有被篡改过。

服务端拿到客户端传来的密文,用自己的私钥来解密握手消息取出随机数密码,再用随机数密码解密握手消息与HASH值,并与传过来的HASH值做对比确认是否一致。
 然后用随机密码加密一段握手消息(握手消息+握手消息的HASH值 )给客户端

客户端用随机数解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密

--------------------------------------------------------------------

“服务器”->“客户”:{OK,已经收到你发来的对称加密算法和密钥!有什么可以帮到你的?}[密钥|对称加密算法]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

“服务器”->“客户”:{你好,你的余额是100元}[密钥|对称加密算法]

…… //继续其它的通信

这里涉及了非对称加密:

非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将公钥公开,需要向甲方发送信息的其他角色(乙方)使用该密钥(甲方的公钥)对机密信息进行加密后再发送给甲方;甲方再用自己私钥对加密后的信息进行解密。甲方想要回复乙方时正好相反,使用乙方的公钥对数据进行加密,同理,乙方使用自己的私钥来进行解密

连接建立之后用对称加密进行通信的原因是:非对称加密的缺点是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比对称加密慢上1000倍。

公钥私钥的加密解密:

第一种用法:公钥加密,私钥解密。---用于加解密
第二种用法:私钥签名,公钥验签。---用于签名

有点混乱,不要去硬记,总结一下:
你只要想:
既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;
既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。

同一种道理,我在换种说法:
私钥和公钥是一对,谁都可以加解密,只是谁加密谁解密是看情景来用的:
第一种情景是签名,使用私钥加密,公钥解密,用于让所有公钥所有者验证私钥所有者的身份并且用来防止私钥所有者发布的内容被篡改.但是不用来保证内容不被他人获得。
第二种情景是加密,用公钥加密,私钥解密,用于向公钥所有者发布信息,这个信息可能被他人篡改,但是无法被他人获得。

比如加密情景:
如果甲想给乙发一个安全的保密的数据,那么应该甲乙各自有一个私钥,甲先用乙的公钥加密这段数据,再用自己的私钥加密这段加密后的数据.最后再发给乙,这样确保了内容即不会被读取,也不会被篡改.

hash:

Hash就是一个工具,能把任意大小的文档变成一个 固定大小(MD5是32个字符)的字符串。并且,这个过程是 不可逆的,也就是说,没有任何办法从那个字符串得到原来那个文档。还有很重要的一点是, 任意两个文档(哪怕极其相似)得到相同字符串的概率几乎等于0。现在你有一个10000字的文章,发给你的朋友,那你的朋友怎么判断他收到的文章一个标点符号都没有少呢?你在发送文章的同时把这个文章的Hash字符串也发过去,这样你的朋友收到文章以后,根据收到的文章重新计算一遍这个字符串,如果这个字符串和你发过去的一样,那就证明你朋友收到的文章是和你发送的一模一样。

http缓存

详细信息见HTTP缓存机制 - ranyonsue - 博客园

对于强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行比较缓存策略。
对于比较缓存,将缓存信息中的Etag和Last-Modified通过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存

例:短时间内查看同一图片,第一次请求返回200,第二次请求返回304 not modified,直接从缓存中取。

解释:在网络上有一些缓存服务器,浏览器自身也有缓存功能。当我们第一次请求某图片时,正常下载图片,返回值200.

此时,基于图片不会经常改动的前提,服务器在返回200的同时,同时还返回该图片的“签名”--Etag(签名可理解为图片的“指纹”)。当浏览器再次访问该图片时,服务器校验Etag,若图片没有发生变化,直接使用缓存中的图片,这样减轻了服务器的负担。

抓包观察:

第一次请求头:

第一次响应头:

第二次请求头:

这两行的意思是:

如果自“Tue,18 Jun 2013 14:04:32 GMT”这个时间点后,图片修改过,则重新请求

或者,如果该图片最新的etag值和 if-Nine-Match的值不匹配,则重新请求

第二次响应信息:

如果是304,就意味着浏览器从本地取缓存,节省了图片在网络上的传输时间

1. 优点

  • 缓解服务器压力;
  • 降低客户端获取资源的延迟:缓存通常位于内存中,读取缓存的速度更快。并且缓存服务器在地理位置上也有可能比源服务器来得近,例如浏览器缓存。

2. 实现方法

  • 让代理服务器进行缓存;
  • 让客户端浏览器进行缓存。

3. Cache-Control

HTTP/1.1 通过 Cache-Control 首部字段来控制缓存。

3.1 禁止进行缓存

no-store 指令规定不能对请求或响应的任何一部分进行缓存。

Cache-Control: no-store

3.2 强制确认缓存

no-cache 指令规定缓存服务器需要先向源服务器验证缓存资源的有效性,只有当缓存资源有效时才能使用该缓存对客户端的请求进行响应。

Cache-Control: no-cache

3.3 私有缓存和公共缓存

private 指令规定了将资源作为私有缓存,只能被单独用户使用,一般存储在用户浏览器中。

Cache-Control: private

public 指令规定了将资源作为公共缓存,可以被多个用户使用,一般存储在代理服务器中。

Cache-Control: public

3.4 缓存过期机制

max-age 指令出现在请求报文,并且缓存资源的缓存时间小于该指令指定的时间,那么就能接受该缓存。

max-age 指令出现在响应报文,表示缓存资源在缓存服务器中保存的时间。

Cache-Control: max-age=31536000

Expires 首部字段也可以用于告知缓存服务器该资源什么时候会过期。

Expires: Wed, 04 Jul 2012 08:26:05 GMT
  • 在 HTTP/1.1 中,会优先处理 max-age 指令;
  • 在 HTTP/1.0 中,max-age 指令会被忽略掉。

4. 缓存验证

需要先了解 ETag 首部字段的含义,它是资源的唯一标识。URL 不能唯一表示资源,例如 http://www.google.com/ 有中文和英文两个资源,只有 ETag 才能对这两个资源进行唯一标识。

ETag: "82e22293907ce725faf67773957acd12"

可以将缓存资源的 ETag 值放入 If-None-Match 首部,服务器收到该请求后,判断缓存资源的 ETag 值和资源的最新 ETag 值是否一致,如果一致则表示缓存资源有效,返回 304 Not Modified。

If-None-Match: "82e22293907ce725faf67773957acd12"

Last-Modified 首部字段也可以用于缓存验证,它包含在源服务器发送的响应报文中,指示源服务器对资源的最后修改时间。但是它是一种弱校验器,因为只能精确到一秒,所以它通常作为 ETag 的备用方案。如果响应首部字段里含有这个信息,客户端可以在后续的请求中带上 If-Modified-Since 来验证缓存。服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为 200 OK。如果请求的资源从那时起未经修改,那么返回一个不带有实体主体的 304 Not Modified 响应报文。

Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT
If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT

DNS

先说一下DNS的几个基本概念:

1.根域

就是所谓的“.”,其实我们的网址www.baidu.com在配置当中应该是www.baidu.com.(最后有一点),一般我们在浏览器里输入时会省略后面的点,而这也已经成为了习惯。

根域服务器我们知道有13台,但是这是错误的观点。

根域服务器只是具有13个IP地址,但机器数量却不是13台,因为这些IP地址借助了任播的技术,所以我们可以在全球设立这些IP的镜像站点,你访问到的这个IP并不是唯一的那台主机。

2.域的划分

根域下来就是顶级域或者叫一级域,

有两种划分方式,一种互联网刚兴起时的按照行业性质划分的com.,net.等,一种是按国家划分的如cn.,jp.,等。

具体多少你可以自己去查,我们这里不关心。

每个域都会有域名服务器,也叫权威域名服务器。

Baidu.com就是一个顶级域名,而www.baidu.com却不是顶级域名,他是在baidu.com 这个域里的一叫做www的主机。

一级域之后还有二级域,三级域,只要我买了一个顶级域,并且我搭建了自己BIND服务器(或者其他软件搭建的)注册到互联网中,那么我就可以随意在前面多加几个域了(当然长度是有限制的)。

比如a.www.baidu.com,在这个网址中,www.baidu.com变成了一个二级域而不是一台主机,主机名是a。

3.域名服务器

能提供域名解析的服务器,上面的记录类型可以是A(address)记录,NS记录(name server),MX(mail),CNAME等。

A记录是什么意思呢,就是记录一个IP地址和一个主机名字,比如我这个域名服务器所在的域test.baidu.com,我们知道这是一个二级的域名,然后我在里面有一条A记录,记录了主机为a的IP,查到了就返回给你了。

如果我现在要想baidu.com这个域名服务器查询a.test.baidu.com,那么这个顶级域名服务器就会发现你请求的这个网址在test.baidu.com这个域中,我这里记录了这个二级域的域名服务器test.baidu.com的NS的IP。我返回给你这个地址你再去查主机为a的主机把。

这些域内的域名服务器都称为权威服务器,直接提供DNS查询服务。(这些服务器可不会做递归哦)

那么我们的DNS是怎么解析一个域名的呢?

1.现在我有一台计算机,通过ISP接入了互联网,那么ISP就会给我分配一个DNS服务器,这个DNS服务器不是权威服务器,而是相当于一个代理的dns解析服务器,他会帮你迭代权威服务器返回的应答,然后把最终查到IP返回给你。

首先依次查看浏览器DNS缓存、操作系统DNS缓存、路由DNS缓存,如果没有想要的ip,则进行下一步

2.现在的我计算机要向这台ISP DNS服务器发起请求查询www.baidu.com这个域名了

3.ISP DNS拿到请求后,先检查一下自己的缓存中有没有这个地址,有的话就直接返回。这个时候拿到的ip地址,会被标记为非权威服务器的应答

4.如果缓存中没有的话,ISPDNS会从配置文件里面读取13个根域名服务器的地址(这些地址是不变的,直接在BIND的配置文件中),然后像其中一台发起请求。

5.根服务器拿到这个请求后,知道他是com.这个顶级域名下的,所以就会返回com域中的NS记录,一般来说是13台主机名和IP。

6.然后ISPDNS向其中一台再次发起请求,com域的服务器发现你这请求是baidu.com这个域的,我一查发现了这个域的NS,那我就返回给你,你再去查。(目前百度有4台baidu.com的顶级域名服务器)。(这就是递归查询)

7.ISP DNS不厌其烦的再次向baidu.com这个域的权威服务器发起请求,baidu.com收到之后,查了下有www的这台主机,就把这个IP返回给你了,

8.然后ISP DNS拿到了之后,将其返回给了客户端,并且把这个保存在高速缓存中。

HTTP协议与内容压缩:

观察我们打开163的一篇新闻,看到如下响应头信息:注意,Content-Length:

同时,我们点击右键保存其源码,得到的文本文件大小:

思考:Content-Length在之前的学习中我们知道,他代表响应报文的主体长度,但此处为什么返回的主体长度和

Content-Length不一致呢

原因在于:Content-Encoding:gzip 这个响应头信息在作用。

原理:为了提高网页在网络上的传输速度,服务器对主体信息进行压缩

如常见的gzip压缩、deflate压缩,compress压缩以及sdch压缩。

上面情况中的Content-Length是压缩后的长度。

如何在apache启用压缩功能?

问题:服务器如何知道浏览器支持gzip的?

->客户端在发送请求时,允许发一个accept-encoding头信息,与服务器协商

http协议的发展过程

HTTP 是基于 TCP/IP 协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。

http/0.9

1991年发布,只有一个命令GET,协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式。

http/1.0

1996年5月发布,HTTP/1.0 版本发布,内容大大增加,首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。除了GET命令,还引入了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段。

HTTP请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。

其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。

**缺点:**

每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。

TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。

为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。

Connection: keep-alive

一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。

http/1.1

1997年1月发布,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了20年后的今天,直到现在还是最流行的版本。

1.1 版的最大变化,就是引入了默认持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。

客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。

HTTP 1.1还新增了如下特性:

请求消息和响应消息都应支持Host头域

在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。因此,Host头的引入就很有必要了。

新增了一批Request method

HTTP1.1增加了OPTIONS,PUT, DELETE, TRACE, CONNECT方法

缓存处理

HTTP/1.1在1.0的基础上加入了一些cache的新特性,引入了实体标签,一般被称为e-tags,新增更为强大的Cache-Control头。

**缺点**

虽然1.1版允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为"队头堵塞"(Head-of-line blocking)。

为了避免这个问题,只有两种方法:

一是减少请求数;

二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。

SPDY

2009年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。这个协议在Chrome浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 之中得到继承。

HTTP/2

2015年,HTTP/2 发布。它不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。

多路复用(二进制分帧)

HTTP 2.0最大的特点: 不会改动HTTP 的语义,HTTP 方法、状态码、URI 及首部字段,等等这些核心概念上一如往常,却能致力于突破上一代标准的性能限制,改进传输性能,实现低延迟和高吞吐量。而之所以叫2.0,是在于新增的二进制分帧层。在二进制分帧层上, HTTP 2.0 会将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码 ,其中HTTP1.x的首部信息会被封装到Headers帧,而我们的request body则封装到Data帧里面。HTTP 2.0 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。相应地,每个数据流以消息的形式发送,而消息由一或多个帧组成,这些帧可以乱序发送,然后再根据每个帧首部的流标识符重新组装。

二进制分帧

先来理解几个概念:

帧:HTTP/2 数据通信的最小单位消息:指 HTTP/2 中逻辑上的 HTTP 消息。例如请求和响应等,消息由一个或多个帧组成。

流:存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数ID。

HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。

HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装。

多路复用

多路复用,代替原来的序列和阻塞机制。所有就是请求的都是通过一个 TCP连接并发完成。 HTTP 1.x 中,如果想并发多个请求,必须使用多个 TCP 链接,且浏览器为了控制资源,还会对单个域名有 6-8个的TCP链接请求限制,如下图,红色圈出来的请求就因域名链接数已超过限制,而被挂起等待了一段时间:

在 HTTP/2 中,有了二进制分帧之后,HTTP /2 不再依赖 TCP 链接去实现多流并行了,在 HTTP/2中:

  • 同域名下所有通信都在单个连接上完成。
  • 单个连接可以承载任意数量的双向数据流。
  • 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。

这一特性,使性能有了极大提升:

  • 同个域名只需要占用一个 TCP 连接,消除了因多个 TCP 连接而带来的延时和内存消耗。
  • 单个连接上可以并行交错的请求和响应,之间互不干扰。
  • 在HTTP/2中,每个请求都可以带一个31bit的优先值,0表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。

服务器推送

服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。

服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三方资源给客户端。

头部压缩

当一个客户端向相同服务器请求许多资源时,像来自同一个网页的图像,将会有大量的请求看上去几乎同样的,这就需要压缩技术对付这种几乎相同的信息。

随时复位

HTTP1.1一个缺点是当HTTP信息有一定长度大小数据传输时,你不能方便地随时停止它,中断TCP连接的代价是昂贵的。使用HTTP2的RST_STREAM将能方便停止一个信息传输,启动新的信息,在不中断连接的情况下提高带宽

HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了"队头堵塞"

HTTPS

HTTPS是HTTP协议的安全版本,HTTP协议的数据传输是明文的,是不安全的,HTTPS使用了SSL/TLS协议进行了加密处理。

反向Ajax

30分钟学会反向Ajax - 冷豪 - 博客园

场景1:当有新邮件的时候,网页自动弹出提示信息而无需用户手动的刷新收件箱。

场景2:当用户的手机扫描完成页面中的二维码以后,页面会自动跳转。

场景3:在类似聊天室的环境中有任何人发言,所有登录用户都可以即时看见信息。

与传统的MVC模型请求必须从客户端发起由服务器响应相比,使用反向Ajax能够模拟服务器端主动向客户端推送事件从而提高用户体验。本文将分两个部分讨论反向Ajax技术,包括:Comet和WebSocket。

TCP网络编程中connect()、listen()和accept()三者之间的关系_Mike江的博客-CSDN博客_accept listen

SOCKET API和TCP STATE的对应关系_三次握手(listen,accept,connect)_四次挥手close及TCP延迟确认(调用一次setsockopt函数,设置TCP_QUICK_Night的博客-CSDN博客

tcp连接过程与三次握手

三次握手对应的Berkeley Socket API:

从图中,可以看出和连接建立相关的API有:connect, listen, accept   3个,connect用在客户端,另外2个用在服务端。

对于TCP/IP protocol stack来说,TCP层的tcp_in&tcp_out也参与这个过程。我们这里只讨论这3个应用层的API干了什么事情。

(1) connect

发送了一个SYN,收到Server的SYN+ACK后,代表连接完成。发送最后一个ACK是protocol stack,tcp_out完成的。

(2)listen

在server这端,准备了一个未完成的连接队列,保存只收到SYN_C的socket结构;这些套接口处于 SYN_RCVD 状态,

准备了已完成的连接队列,即保存了收到了最后一个ACK的socket结构。这些套接口处于 ESTABLISHED 状态。

     这里需要注意的是,listen()函数不会阻塞,它主要做的事情为,将该套接字和套接字对应的连接队列长度告诉 Linux 内核,然后,listen()函数就结束。

(3)accept

应用进程调用accept的时候,就是去检查上面说的已完成的连接队列,如果队列里有连接,就返回这个连接;

如果没有,即空的,blocking方试调用,就睡眠等待;

nonblocking方式调用,就直接返回,一般一"EWOULDBLOCK“ errno告诉调用者,连接队列是空的。

 注意:

在上面的socket API和TCP STATE的对应关系中,TCP协议中,客户端收到Server响应时,可能会有会延迟确认。

即客户端收到数据后,会阻塞给Server端确认。

可以在每次收到数据后:

调用setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){1}, sizeof(int));  快速给Server端确认。

listen函数的未完成连接队列中:当来自客户的 SYN 到达时,TCP 在未完成连接队列中创建一个新项,然后响应以三次握手的第二个分节:服务器的 SYN 响应,其中稍带对客户 SYN 的 ACK(即SYN+ACK),这一项一直保留在未完成连接队列中,直到三次握手的第三个分节(客户对服务器 SYN 的 ACK )到达或者该项超时为止(曾经源自Berkeley的实现为这些未完成连接的项设置的超时值为75秒)。

如果三次握手正常完成,该项就从未完成连接队列移到已完成连接队列的队尾。

accept()函数功能是,从处于 established 状态的连接队列头部取出一个已经完成的连接,如果这个队列没有已经完成的连接,accept()函数就会阻塞,直到取出队列中已完成的用户连接为止。

Time_wait

关闭链接过程中的TCP状态和SOCKET处理,及可能出现的问题:

1. TIME_WAIT

TIME_WAIT 是主动关闭 TCP 连接的那一方出现的状态,系统会在 TIME_WAIT 状态下等待 2MSL(maximum segment lifetime  )后才能释放连接(端口)。通常约合 4 分钟以内。

进入 TIME_WAIT 状态等待 2MSL 的目的:

1、确保连接可靠地关闭; 即防止最后一个ACK丢失。

2、避免产生套接字混淆(同一个端口对应多个套接字)。

(

意思是,一方close发送了关闭链接请求,对方的应答迟迟到不了(例如网络原因),导致TIME_WAIT超时,此时这个端口又可用了,

我们在这个端口上又建立了另外一个socket链接。

如果此时对方的应答到了,怎么处理呢?

其实这个在TCP层已经处理了,由于有TCP序列号,所以内核TCP层,就会将包丢掉,并给对方发包,让对方将sockfd关闭。

所以应用层是没有关系的。即我们用socket API编写程序,就不用处理。

)

注意::

TIME_WAIT是指操作系统的定时器会等2MSL,而主动关闭sockfd的一方,并不会阻塞。(即应用程序在close时,并不会阻塞)。

当主动方关闭sockfd后,对方可能不知道这个事件。那么当对方(被动方)写数据,即send时,将会产生错误,即errno为: ECONNRESET。

服务器产生大量 TIME_WAIT 的原因:(一般我们不这样开发Server)

服务器存在大量的主动关闭操作,需关注程序何时会执行主动关闭(如批量清理长期空闲的套接字等操作)。

一般我们自己写的服务器进行主动断开连接的不多,除非做了空闲超时之类的管理。(TCP短链接是指,客户端发送请求给服务器,客户端收到服务器端的响应后,关闭链接)。

修改timewait的MSL:

#Linux,以CentOS为例:#查看默认的MSL值(60s):[root@DanCentOS65var]$ cat /proc/sys/net/ipv4/tcp_fin_timeout60#修改默认60为120:[root@DanCentOS65var]$ echo 120 > /proc/sys/net/ipv4/tcp_fin_timeout#修改完成后,重新加载配置文件:[root@DanCentOS65var]$ sysctl -p /etc/sysctl.conf#查看是否已经生效:[root@DanCentOS65var]$ sysctl -a | grep finnet.ipv4.tcp_fin_timeout= 120

2. CLOSE_WAIT

CLOSE_WAIT 是被动关闭 TCP 连接时产生的,

如果收到另一端关闭连接的请求后,本地(Server端)不关闭相应套接字就会导致本地套接字进入这一状态。

(如果对方关闭了,没有收到关闭链接请求,就是下面的不正常情况)

按状态机,我方收到FIN,则由TCP实现发送ACK,因此进入CLOSE_WAIT状态。但如果我方不执行close(),就不能由CLOSE_WAIT迁移到LAST_ACK,则系统中会存在很多CLOSE_WAIT状态的连接。

如果存在大量的 CLOSE_WAIT,则说明客户端并发量大,且服务器未能正常感知客户端的退出,也并未及时 close 这些套接字。(如果不及时处理,将会出现没有可用的socket描述符的问题,产生问题的原因,没有及时close)。

正常情况下,一方关闭sockfd,另外一方将会有读事件产生, 当recv数据时,如果返回值为0,表示对端已经关闭。此时我们应该调用close,将对应的sockfd也关闭掉。

不正常情况下,一方关闭sockfd,另外一方并不知道,(比如在close时,自己断网了,对方就收不到发送的数据包)。此时,如果另外一方再向对应的sockfd上写send或读recv数据。

recv时,将会返回0,表示链接已经断开。

send时, 将会产生错误,errno为ECONNRESET。

此部分原文见  Content-Type 详解_leoss.H的博客-CSDN博客_content-type

Content-Type

Content-Type(MediaType),即是Internet Media Type,互联网媒体类型,也叫做MIME类型。在互联网中有成百上千中不同的数据类型,HTTP在传输数据对象时会为他们打上称为MIME的数据格式标签,用于区分数据类型。最初MIME是用于电子邮件系统的,后来HTTP也采用了这一方案。

在HTTP协议消息头中,使用Content-Type来表示请求和响应中的媒体类型信息。它用来告诉服务端如何处理请求的数据,以及告诉客户端(一般是浏览器)如何解析响应的数据,比如显示图片,解析并展示html等等。

Content-Type的格式:

Content-Type:type/subtype ;parameter

type:主类型,任意的字符串,如text,如果是*号代表所有;
subtype:子类型,任意的字符串,如html,如果是*号代表所有,用“/”与主类型隔开;
parameter:可选参数,如charset,boundary等。
例如:
Content-Type: text/html;
Content-Type: application/json;charset:utf-8;

常见Content-Type

常见的Content-Type有数百个,下面例举了一些

HTML文档标记:text/html;
普通ASCII文档标记:text/html;
JPEG图片标记:image/jpeg;
GIF图片标记:image/gif;
js文档标记:application/javascript;
xml文件标记:application/xml;

application/x-www-form-urlencoded
HTTP会将请求参数用key1=val1&key2=val2的方式进行组织,并放到请求实体里面,注意如果是中文或特殊字符如"/"、","、“:" 等会自动进行URL转码。不支持文件,一般用于表单提交。

multipart/form-data
与application/x-www-form-urlencoded不同,这是一个多部分多媒体类型。首先生成了一个 boundary 用于分割不同的字段,在请求实体里每个参数以------boundary开始,然后是附加信息和参数名,然后是空行,最后是参数内容。多个参数将会有多个boundary块。如果参数是文件会有特别的文件域。最后以------boundary–为结束标识。multipart/form-data支持文件上传的格式,一般需要上传文件的表单则用该类型。

application/json
JSON 是一种轻量级的数据格式,以“键-值”对的方式组织的数据。这个使用这个类型,需要参数本身就是json格式的数据,参数会被直接放到请求实体里,不进行任何处理。服务端/客户端会按json格式解析数据(约定好的情况下)。

application/xml 和 text/xml
与application/json类似,这里用的是xml格式的数据,text/xml的话,将忽略xml数据里的编码格式。

网络基础知识理解:

1.数据链路层:

信息单元:frame 数据帧

设备:交换机,实质上是一个多接口的网桥,每个接口都直接与一个单台主机或者另一个以太网交换机相连,一般工作在全双工方式,能同时联通多对接口,使多对主机同时通信,且都是独占传输媒体(而非共享带宽),无碰撞地传输数据。    主机和接口的映射关系是通过内部自学习的帧交换表(地址表)建立起来的。

协议:点对点PPP协议,特点:

  • 封装成帧
  • 透明传输(转义字节填充0x7D、零比特填充--连续5个1就填上一个0)
  • 差错校验
  • 多种网络协议
  • 最大传输单元(MTU) --数据部分最大长度如1500字节

2.网络层

IP协议详解 - Red_Code - 博客园

信息单元:datagram  数据报

设备:路由器,将网络分为独立子网,连接多个逻辑上分开的网络,可判断网络地址和选择ip路径

协议:ip协议、ARP协议、ICMP协议、IGMP协议

基本的IP地址结构

分类寻址

IPV4被分为五大类:ABCDE

A类为:点分四组中的第一组地址范围为0~127的IP地址。已二进制来看就是“首位为0”

B类:128~191.二进制首位为10

C类:192~223.二进制首位为110

D类:224~239.二进制首位为1110 用于ip多播

E类:240~255.二进制首位为1111 保留

子网寻址

如上可以看出,IP地址值存在两个子结构:网络号和主机ID,但这样就出现了一个问题。就是分配ip地址很麻烦。(即网络信息中心要负责每一台主机的ip地址分配,这样就太繁杂了。)。

于是就将ip地址从两级分成了三级:网络号、子网ID、主机ID

划分子网ID的方法是从“原有的主机号中借用若干位”作为子网号。(当然,主机号就减少了)

网络信息中心集中分配每一个网络号。

然后各个站点的管理人员再分配他们网络号下的子网ID和对应的主机ID。然后管理员在安排每一个子网下面的主机数。

子网掩码

在ip地址传播的时候,可以根据二进制首位的格式判断其属于第几类网,也就爱能判断其网络号有多少位。

但ip地址本身并没有包含任何关于子网划分的信息,所以光凭ip地址无法知道“其是如何划分子网的”。

于是就出现了子网掩码,和ip地址配套着出现,用来说明“该ip地址的子网ID是那几位数”。

图示如下:

以二进制来看子网掩码,只有“连续的1”或“连续的0”。IP子网掩码的长度和他所对应的IP地址长度一样(即32位和128位)。

其中的“1”对应的是ip中的“网络号”和“子网号”,“0”对应的是ip中的“主机号”。

将ip地址与子网掩码进行“按位与”运算,就能得出用于路由的“子网标识符”,如:

ip地址:  128.32.1.14 对应二进制:10000000 00100000 00000001 00001110

掩码地址: 255.255.255.0 对应二进制:11111111 11111111 11111111 00000000

子网标识符 128.32.1.0 对应二进制:10000000 00100000 00000001 00000000

通过上面的运算我们可以看出:128.32.1.14这个地址属于子网“128.32.1.0”。

以上面的各个ip地址为例,整个流程可以如下所示:

1、某个站点申请到了一个B类网的网络号:128.32.x.x

2、然后该站点的管理员决定使用“255.255.255.0”作为该站点的子网掩码。这样就该站点有多少个子网划分好了

(一旦决定使用该子网掩码,通过计算就能知道,将该站点划分了256个子网,每个子网里有254台主机(因为每个子网的第一个和最后一个地址无效))

3、然后为每一个子网中的主机都安排好ip地址。

4、假设现在有一个访问,请求访问ip地址128.32.1.14

5、先根据该ip地址的二进制前几位,发现该地址是一个B类网,所以网络号有16位,也就是说128.32是它的网络号。于是根据网络号128.32找到该站点。

6、该站点边界路由器将该ip与子网掩码进行“按位与”运算,发现子网标识符为128.32.1.0(即128.32.1,后面的.0不存在,因为每个子网的第一个和最后一个地址无效)

7、找到子网128.32.1后,再根据.14找到主机。

ip路由转发的过程

比如:A访问B,

首先对比是否同一子网,如果是,检查ARP表,有B的MAC就直接发送,没有就发送ARP请求.如果否,发送到默认网关C,源IP为A,源MAC为A,目的IP为B,目的MAC地址为C

C接收到这个包,检查路由表,发送到下一跳D,IP为AMAC为C目的IP为B目的MAC为D…..

如此循环,直到发送到B.

此过程中的源ip、目的ip是不变的,改变的是MAC地址,由路由器的mac地址决定。直到此路由器所在子网是我们的目的ip所在子网(用子网掩码和目标ip进行与运算),就查ARP表,发给目的主机

每台主机都有ARP高速缓存,并设有生存时间。若本机A刚加电或者对方主机B刚入网,则A广播ARP请求(带有自身ip、自身MAC、目标ip),当B收到广播,先将A的ip-MAC写入高速缓存,然后单播ARP响应,告诉A自己的MAC。

从上面描述可以看出,当主机AB在同一局域网时,直接可以ARP得到MAC,当不在同一网络时,就先将ip数据报发给本网络的路由器,直到此ip数据报由路由器转发到目标机器所在的网络为止。

主机和路由器都能转发ip,不同之处在于:主机不转发那些不是由它生成的数据报,但路由器会转发。

IP地址可以接收一个数据报。

当IP模块接收到一个数据报时,首先检查此数据报的目的地址是否为自己的IP地址,

如果不是,且IP层配置为一台路由器,则根据“转发表”转发该数据报。

否则丢弃此数据报,然后返回给源节点一个信息,表明错误。

具体步骤:

  1. 从数据报的首部提取出目的主机的ip地址D,得出目的网络地址N
  2. 若N就是与此路由器直接相连的某个网络地址,则进行直接交付,不需要再经过其他的路由器,直接把数据报交付给目的主机(这里包括把目的主机地址D转换为具体的硬件地址,把数据报封装成为MAC帧,再发送此帧);否则就是间接交付,执行3
  3. 若路由表中有目的地址为D的特定主机路由,则把数据报传送给路由表中所指明的下一跳路由器;否则执行4
  4. 若路由表中有到达网络N的路由,则把数据报传送给路由表中所指明的下一跳路由器,否则执行5
  5. 若路由表中有一个默认路由,则把数据报传送给路由表中所指明的默认路由器;否则执行6
  6. 报告转发分组出错

ip数据报格式:

标识、标志、分偏移:

该字段帮助标识由IPv4主机发送的数据报。

这个字段对实现分片很重要,大多数数据链路层不支持过长的ip数据报(如MTU为1500字节),所以要把ip数据报分片,每一片都是一个独立的ipv4数据报。

发送主机每次发送数据报都讲一个“内部计数器”加1,然后将数值赋值“标识”字段中。

在接收方收到一些数据报后,将相同标识的数据报整合在一起(结合片偏移),得到完整的一份ip数据报。

ICMP协议

[na]完全理解icmp协议 - _毛台 - 博客园

ICMP协议_binger-csdn的博客-CSDN博客_icmp协议

协议头

应用场景:

1.MTU探测

2.ping

3. trace route

有关路由选择协议的几个概念
1、理想的路由算法
路由选择协议的核心就是路由算法,即路由器通过算法来获得路由。
一个理想的路由算法应该具有以下的特点

  • 算法必须是正确和完整的
  • 算法在计算上应简单
  • 算法应能适应通信量和网络拓扑的变化
  • 算法应具有稳定性
  • 算法应是公平的
  • 算法应是最佳的

这里的“最佳”指的是相对于某一种特定要求下得出的较为合理的选择
从路由算法能否适应通信量和网络拓扑的变化来看,可将路由分为

  • 静态路由:由管理员进行配置,路由不随网络拓扑的变化而变化
  • 动态路由:自动学习路由,路由能够适时根据网络拓扑的变化而变化

由于因特网规模较大,不可能要求管理员为因特网上所有的路由器去配置路由。而且因特网上的网络拓扑随时都在变,管理员配置的静态路由也无法去适应网络拓扑的变化。所以,因特网上采用的主要是动态的、分布式路由协议。
同时,一些企业部门不希望自己的内部网络被外界知道,所以因特网将整个互联网划分为许多小的自制系统(AS)
AS的定义:在单一的技术管理下的一组路由器。一个AS对其他AS表现出的是一个单一的和一致的路由选择策略。
根据此,可以将路由选择协议划分为两大类

  • 内部网关协议(IGP):在一个自治系统内部使用的路由协议(RIP或者OSPF)
  • 外部网关协议(EGP):在自治系统间进行路由的路由协议,典型的外部网关协议就是BGP,现在使用最多的是BGP-4(BGP协议的4版本)

RIP协议
RIP协议是一种分布式的基于路由矢量的路由选择协议(贝尔曼-福特算法)
这里的“距离”是跳数,即每经过一个路由器,距离加1,RIP协议规定距离最大为16,当距离等于16时,相当于不可达。所以这个也就注定RIP只能适用于小型互联网
RIP协议的特点

  • 仅和相邻路由器交换信息(相邻说的是直连的路由器)
  • 路由器交换的信息是当前路由器知道的全部信息,即自己的路由表
  • 按规定的时间间隔交换路由信息,周期为30s

OSPF协议
为了克服RIP协议存在的缺点,在1989年开发出了OSPF协议,使用了最短路径算法(Dijkstra迪杰斯特拉算法)。
OSPF协议最主要的特征是使用分布式的链路状态协议
三个要点

  • 所有路由器向本自治系统中的其他所有路由器用洪泛发送信息
  • 发送的信息就是与本路由器相邻的所有路由器的链路状态通告(LSA)

这里的链路状态是指本路由器都和那些路由器相邻,以及该链路的度量(或者称为代价)。这个度量用来表示费用、距离、时延、带宽等,由网络管理人员来决定。

  • 只有当链路状态发生变化时,路由器才向所有路由器用洪泛法发送此信息

OSPF协议工作过程
1.发现邻居,建立并维护邻居关系
2.生成LSA,每台路由器都会生成自己的LSA
3.泛洪LSA,使用OPSF自身具备可靠传输能力将LSA泛洪到区域中的其它路由器上
4.将收到的LSA组装成链路状态数据库(LSDB),根据SPF算法计算出到达拓扑中所有网络的最短路径
5.将计算得出的路由装载到路由表

OSPF协议的优点

  • 收敛速度快
  • 网络扩展性好
  • 环路避免方面性能较好

为了能使OSPF适用于更大规模的网络,OSPF将一个自治系统在划分为若干个区域(area)每个区域有一个32位的区域标识符(用点分十进制表示)一个区域不能太大,在区域进行规划的时候,一般要根据一个区域内路由器的型号,性能,以及负载来进行设计,通常一个区域中的路由器数量为30到100台左右,最好不要超过200台路由器
    划分区域的好处就是把利用洪泛法交换链路状态信息的范围局限于每一个区域而不是整个自治系统,这样就减少了整个网络上的通信量。OSPF采用层次结构的区域划分,分为主干区域和普通区域。
    区域在进行规划的时候,一定要注意,所有普通区域必须与骨干区域直接相连。该要求主要是为了OSPF区域间防环。(由于SPF算法本身可以保证OSPF在区域内部无环路,所以区域间防环主要依靠网络设计来解决。因为OSPF在区域间使用类似距离矢量路由协议的路由传递方式,所以不能保证没有环路,如果所有普通区域都直接连接到骨干区域,相当于形成了一个星型拓扑,这在拓扑的设计上避免了区域间环路的可能。

3.传输层

协议:tcp,udp

信息单元:segment 数据段

网络层为主机之间提供逻辑通信,运输层为应用进程之间提供端到端的逻辑通信。

tcp报文首部:20字节的固定首部+4n字节的选项(不超过40字节的选项,因为表示首部长度只有4位,因此首部最多(1111即)15*4=60字节长)

tcp是面向字节流的传输协议,流是指流入进程或从进程流出的字节序列。tcp并不关心应用进程一次把多长的报文发送到tcp的缓存中,而是根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文段应该包含多少个字节(udp发送的报文段长度是应用进程给出的)。如果进程传送到tcp缓存的数据块太长,tcp可以把它划分短一些再传送;如果进程一次只发来一个字节,tcp也可以等待积累有足够多的字节后再构成报文段发送出去。

状态转换图:

连接的建立与断开:

正常情况下, tcp需要经过三次握手建立连接, 四次挥手断开连接.

那么什么是三次握手? 什么是四次挥手呢?

三次握手

第一次: 
客户端 - - > 服务器 此时服务器知道了客户端要建立连接了  SYN,seq=x
第二次: 
客户端 < - - 服务器 此时客户端知道服务器收到连接请求了   SYN,ACK,ack=x+1,seq=y
第三次: 
客户端 - - > 服务器 此时服务器知道客户端收到了自己的回应  ACK,ack=y+1,seq=x+1

到这里, 就可以认为客户端与服务器已经建立了连接.

具体步骤:

刚开始, 客户端和服务器都处于 CLOSE 状态. 
此时, 客户端向服务器主动发出连接请求, 服务器被动接受连接请求.

1, TCP服务器进程先创建传输控制块TCB, 时刻准备接受客户端进程的连接请求, 此时服务器就进入了 LISTEN(监听)状态 
2, TCP客户端进程也是先创建传输控制块TCB, 然后向服务器发出连接请求报文,此时报文首部中的同步标志位SYN=1, 同时选择一个初始序列号 seq = x, 此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定, SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。 
3, TCP服务器收到请求报文后, 如果同意连接, 则发出确认报文。确认报文中的 ACK=1, SYN=1, 确认序号是 x+1, 同时也要为自己初始化一个序列号 seq = y, 此时, TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据, 但是同样要消耗一个序号。 
4, TCP客户端进程收到确认后还, 要向服务器给出确认。确认报文的ACK=1,确认序号是 y+1,自己的序列号是 x+1. 
5, 此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。

  • 为什么不用两次?

主要是为了防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送的第一个请求连接并且没有丢失,只是因为在网络中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时之前滞留的那一次请求连接,因为网络通畅了, 到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的费。 
如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

  • 为什么不用四次?

因为三次已经可以满足需要了, 四次就多余了.

再来看看何为四次挥手. (服务端多一个传输数据的过程,因此多一次挥手)

TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。

数据传输完毕后,双方都可以释放连接. 
此时客户端和服务器都是处于ESTABLISHED状态,然后客户端主动断开连接,服务器被动断开连接.

  • 1, 客户端进程发出连接释放报文,并且停止发送数据。

释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。

  • 2, 服务器收到连接释放报文,发出确认报文,ACK=1,确认序号为 u+1,并且带上自己的序列号seq=v,此时服务端就进入了CLOSE-WAIT(关闭等待)状态。

TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

  • 3, 客户端收到服务器的确认请求后,此时客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最终数据)
  • 4, 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,确认序号为v+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  • 5, 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,确认序号为w+1,而自己的序列号是u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。 若在2MSL时间内服务端没收到此ACK,服务端会重发上一个FIN,因此若
  • 6, 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

【断连过程总结】

1)close只是减少socket文件的引用计数,当计数减为0后,操作系统执行tcp的断连操作

2)client端close后server端不close,会导致client端连接状态为FIN_WAIT_2,server端连接状态为CLOSE_WAIT

正常编程肯定不会这样处理,一般都是在异常处理跳转(C++/JAVA等)导致没有close,或者整个系统异常导致没有close(例      如JVM内存出现out of memory错误)

3)shutdown的处理逻辑比较复杂,非特殊情况不要乱用,很容易出问题

4)进程退出后操作系统会自动回收socket,发起tcp关闭流程操作

tcp有一个MSS(最大分节大小),用于向对端tcp通告对端在每个分节中能发送的最大tcp数据量。MSS的目的是告诉对端其重组缓冲区大小的实际值,从而试图避免分片。MSS经常设置成MTU减去IP和TCP首部额固定长度。

在以太网中使用ipv4的MSS值为1460,使用ipv6的MSS值为1440(二者tcp首部都是20字节,而ipv4首部20字节,ipv6首部40字节)

确认应答机制、超时重传机制、滑动窗口、流量控制、拥塞控制等见  tcp协议详解

https://blog.csdn.net/yao5hed/article/details/81046945

滑动窗口:

概述
滑动窗口实现了TCP流控制。首先明确滑动窗口的范畴:TCP是双工的协议,会话的双方都可以同时接收和发送数据。TCP会话的双方都各自维护一个发送窗口和一个接收窗口。各自的接收窗口大小取决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。各自的发送窗口则要求取决于对端通告的接收窗口,要求相同。

滑动窗口解决的是流量控制的的问题,就是如果接收端和发送端对数据包的处理速度不同,如何让双方达成一致。接收端的缓存传输数据给应用层,但这个过程不一定是即时的,如果发送速度太快,会出现接收端数据overflow,流量控制解决的是这个问题。

窗口的概念
发送方的发送缓存内的数据都可以被分为4类: 
1. 已发送,已收到ACK 
2. 已发送,未收到ACK 
3. 未发送,但允许发送 

4. 未发送,但不允许发送

其中类型2和3都属于发送窗口。  发送窗口的大小不能超过接收窗口的大小,应该随之改变(同时受到拥塞窗口的影响)

接收方的缓存数据分为3类: 
1. 已接收 
2. 未接收但准备接收 
3. 未接收而且不准备接收

其中类型2属于接收窗口。

窗口大小代表了设备一次能从对端处理多少数据,之后再传给应用层。缓存传给应用层的数据不能是乱序的,窗口机制保证了这一点。现实中,应用层可能无法立刻从缓存中读取数据。

滑动机制
发送窗口只有收到发送窗口内字节的ACK确认,才会移动发送窗口的左边界。

接收窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保对端会对这些数据重传。

遵循快速重传、累计确认、选择确认等规则。

发送方发的window size = 8192;就是接收端最多发送8192字节,这个8192一般就是发送方接收缓存的大小。

分析:

36之前的是接收方已经回复了ACK确认收到的,因此发送方可以丢弃备份。

37~51是已发送但未确认,发送方要保留备份数据,52~56是允许发送但是尚未发送。

若接收方收到了37,38,39,42,43,则回复ACK 40,表示40没收到,但是40之前的都收到了,因此发送方将发送窗口左边界前移3格(右边界是否前移要看接受窗口大小是不是保持不变,若是变小了可能就不能前移)。

若接收方又收到了44,45,46,则回复ACK 40表示40还没收到,发送窗口不能前移。若发送窗口中的所有数据都发了,但还没收到ACK确认(可能接收方的确认丢失了),就不能再发送数据了(等待RTO时间后重传这些数据)。

值得注意的是,若发送放连续接到3个40,则会触发快重传算法,立即重传40,而不等到RTO时间。

三个指针确定滑动窗口:

流量控制

流量控制的主要有两个重要的点要掌握。一 是TCP利用滑动窗口来实现流量控制机制; 二 是考虑流量控制中的传输效率。

1.流量控制

所谓的流量控制,主要是接收方传递信息给发送方,使其不要发送数据太快,而是一种端到端的控制。

主要的控制方法:接收窗口通过返回的ACK,其中会包含自己的接受窗口的大小,并且利用大小来控制发送方的数据发送:

流量控制实现是通过确认号+窗口大小实现的,就是通知发送方可以发送600之后的100个字节

这里面涉及到一种情况,如果B已经告诉A自己的缓冲区已满,于是A停止发送数据;等一段时间后,B的缓冲区出现了富余,于是发送报文告诉A我的RWND大小为400,但是这个报文不幸丢失了,于是就出现了A等待B的通知 || B等待A发送数据的死锁状态。

为了解决这个问题,TCP引入了持续计时器(Persistence timer)当A收到对方的零窗口通知时,就启动该计时器,时间到则发送一个字节的探测报文,对方会在此时回应自身的接受窗口的大小,如果结果仍为0,则重设持续计时器(更新),继续等待。

拥塞控制:

tcp拥塞控制包括了四个算法:慢开始、拥塞避免、快重传和快恢复

1.慢开始

a.算法原理:

当主机开始发送数据时,如果立即将大量数据字节注入到网络,那么就有可能因为不清楚当前网络的负荷情况而引起网络阻塞。所以,最好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。通常在刚刚发送报文段时,先把拥塞窗口cwnd设置为一个最大报文段MSS的数值。而在每收到一个新的报文段的确认后,把拥塞窗口增大一倍。用这样的方法逐步增大发送方的拥塞窗口cwnd,可以使分组注入到网络的速率更加合理。(慢开始当中的“慢”并不是指cwnd的增长速率慢,而是在TCP开始发送报文段时先设置cwnd = 1,使得发送方在开始时只发送一一个报文段)

当rwnd足够大的时候,为了防止拥塞窗口cwnd的增长引起网络阻塞,还需要另外一个变量------慢开始门限ssthresh.

i.当cwnd < ssthresh时,使用上述慢启动算法;

ii.当cwnd >ssthresh时,停止使用慢启动算法,改用拥塞避免算法;

b.慢开始的局限性

i.需要获得网络内部流量分布的信息,浪费可用的网络容量,额外开销;

ii.估算合理的ssthresh值并不容易,可能耗时较长;

注:i.接收端窗口rwnd,又称通知窗口(awnd),是接收端根据目前的接收缓存大小所许诺的最新窗口值,是来自接收端的流量控制。

ii.拥塞窗口cwnd是发送端根据自己估计的网络阻塞程度而设置的窗口值,是来自发送端的流量控制。

iii.MSS是TCP数据包每次能够传输的最大数据分段,其中并不包括TCP首部。而MSS只出现在syn报文段当中。一般来说MSS的值在不分段的情况下越大越好(eg:一个外出接口的MSS值时MTU减去IP和TCP首部长度)

2.拥塞避免

a.算法思路:让拥塞窗口cwnd缓慢的增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍,这样拥塞窗口cwnd按线性规律缓慢的增长,比慢开始算法的拥塞窗口增长速率缓慢的多

无论是慢启动算法还是拥塞避免算法,只要判断网络出现拥塞,就要把慢启动开始门限(ssthresh)设置为发送窗口的一半(>=2),cwnd设置为1,然后再使用慢启动算法,这样做的目的能迅速的减少网络当中的数据传输,使发生拥塞的路由器能够把队列中堆积的分组处理完毕。拥塞窗口是按照线性的规律增长

3.快重传

一条TCP连接有时会因为等待重传计时的超时而空闲较长时间,慢开始和拥塞避免无法解决这类问题,因此提出了快重传和快恢复的拥塞控制方法。

a.算法过程:

快重传算法要求首先接收方收到一个失序的报文段后立刻发出重复确认,而不要等待自己发送数据时才进行捎带确认,如下图

在上图中,接收方成功的接受了发送方发来的M1,M2并且分别发送了ACK,现在接收方没有收到M3,而收到了M4,显然接收方不能确认M4,因为M4是失序的报文段。如果根据可靠性传输原理接收方什么都不做,但是按照快速重传算法,在收到M4,M5等报文段的时候,不断重复的向发送方发送M2的ACK,如果接收方一连收到三个重复的ACK,那么发送方不必等待重传计时器到期,由于发送方尽早重传未被确认的报文段

4.快恢复

i.当发送方连续收到三个重复确认时,执行“乘法减小”算法,慢启动门限减半,为了预防网络发生阻塞

ii.由于发送方现在认为网络很可能没有发生阻塞,因此现在不执行慢启动算法,而是把cwnd值设置为慢启动门限减半后的值,然后开始执行拥塞避免算法,拥塞窗口cwnd值线性增大

udp

这里注意一下udp的报头格式

关心端口,ip地址是由运输层dns协议拿到再放入网络层。首部共占8字节,比tcp小多了。

1.源端口: 源端口号,需要对方回信时选用,不需要时全部置0.
2.目的端口:目的端口号,在终点交付报文的时候需要用到。
3.长度:UDP的数据报的长度(包括首部和数据)其最小值为8(只有首部)
4.校验和:检测UDP数据报在传输中是否有错,有错则丢弃。
该字段是可选的,当源主机不想计算校验和,则直接令该字段全为0.
当传输层从IP层收到UDP数据报时,就根据首部中的目的端口,把UDP数据报通过相应的端口,上交给应用进程。
如果接收方UDP发现收到的报文中的目的端口号不正确(不存在对应端口号的应用进程0,),就丢弃该报文,并由ICMP发送“端口不可达”差错报文给对方。

UDP是传输层的协议,功能即为在IP的数据报服务之上增加了最基本的服务:复用和分用以及差错检测。

  • UDP提供不可靠服务,具有TCP所没有的优势:
  • UDP无连接,时间上不存在建立连接需要的时延。空间上,TCP需要在端系统中维护连接状态,需要一定的开销。此连接装入包括接收和发送缓存,拥塞控制参数和序号与确认号的参数。UCP不维护连接状态,也不跟踪这些参数,开销小。空间和时间上都具有优势。

举个例子:

DNS如果运行在TCP之上而不是UDP,那么DNS的速度将会慢很多。
HTTP使用TCP而不是UDP,是因为对于基于文本数据的Web网页来说,可靠性很重要。
同一种专用应用服务器在支持UDP时,一定能支持更多的活动客户机。

  • 分组首部开销小,TCP首部20字节,UDP首部8字节。
  • UDP没有拥塞控制,应用层能够更好的控制要发送的数据和发送时间,网络中的拥塞控制也不会影响主机的发送速率。某些实时应用要求以稳定的速度发送,能容 忍一些数据的丢失,但是不能允许有较大的时延(比如实时视频,直播等)
  • UDP提供尽最大努力的交付,不保证可靠交付。所有维护传输可靠性的工作需要用户在应用层来完成。没有TCP的确认机制、重传机制。如果因为网络原因没有传送到对端,UDP也不会给应用层返回错误信息
  • UDP是面向报文的,对应用层交下来的报文,添加首部后直接乡下交付为IP层,既不合并,也不拆分,保留这些报文的边界。对IP层交上来UDP用户数据报,在去除首部后就原封不动地交付给上层应用进程,报文不可分割,是UDP数据报处理的最小单位。

正是因为这样,UDP显得不够灵活,不能控制读写数据的次数和数量。比如我们要发送100个字节的报文,我们调用一次sendto函数就会发送100字节,对端也需要用recvfrom函数一次性接收100字节,不能使用循环每次获取10个字节,获取十次这样的做法。

  • UDP常用一次性传输比较少量数据的网络应用,如DNS,SNMP等,因为对于这些应用,若是采用TCP,为连接的创建,维护和拆除带来不小的开销。UDP也常用于多媒体应用(如IP电话,实时视频会议,流媒体等)数据的可靠传输对他们而言并不重要,TCP的拥塞控制会使他们有较大的延迟,也是不可容忍的

UDP包大小限制

以太网(Ethernet)数据帧的长度必须在46-1500字节之间,这是由以太网的物理特性决定的,这个1500字节被称为链路层的MTU(最大传输单元)。 但这并不是指链路层的长度被限制在1500字节,其实这这个MTU指的是链路层的数据区,并不包括链路层的首部和尾部的18个字节。

所以,事实上这个1500字节就是网络层IP数据报的长度限制。因为IP数据报的首部为20字节,所以IP数据报的数据区长度最大为1480字节。而这个1480字节就是用来放TCP传来的TCP报文段或UDP传来的UDP数据报的。

又因为UDP数据报的首部8字节,所以UDP数据报的数据区最大长度为1472字节。这个1472字节就是我们可以使用的字节数​​​​​​​。

这也就是说IP数据报大于1500字节,大于MTU,这个时候发送方IP层就需要分片(fragmentation)。把数据报分成若干片,使每一片都小于MTU,而接收方IP层则需要进行数据报的重组。这样就会多做许多事情,而更严重的是,由于UDP的特性,当某一片数据传送中丢失时,接收方无法重组数据报,将导致丢弃整个UDP数据报。

因此,在普通的局域网环境下,我建议将UDP的数据控制在1472字节以下为好。

应用层的一些协议:

应用 应用层协议 端口号 传输层协议 备注
域名解析 DNS 53 UDP/TCP 长度超过 512 字节时使用 TCP
动态主机配置协议 DHCP 67/68 UDP
简单网络管理协议 SNMP 161/162 UDP
文件传送协议 FTP 20/21 TCP 控制连接 21,数据连接 20
远程终端协议 TELNET 23 TCP
超文本传送协议 HTTP 80 TCP
简单邮件传送协议 SMTP 25 TCP
邮件读取协议 POP3 110 TCP
网际报文存取协议 IMAP 143 TCP

ssh    用的是22号端口

贴一个很好的文章链接:cyc的github

【学习点滴】网络相关理解与http协议相关推荐

  1. python网络编程需要学什么,python网络编程学习笔记(五):socket的一些补充 Python 网络编程需要学习哪些网络相关的知识...

    python的socket编程问题hdr = recvall(s, 5) if hdr is None: print 'Unexpected EOF receivingstruct在unpack的时候 ...

  2. Linux学习之网络相关命令

    Linux的核心,网络相关 很多工具也是通过分析加工 /proc./sys 下的数据来工作的,而那些更加细致.专业的性能监测和调优,可能还需要更加专业的工具(perf.systemtap等)和技术才能 ...

  3. python网络编程视频教程_Java网络开发视频教程 – 一站式学习Java网络编程视频教程 全面理解BIO(无密)...

    Java网络开发视频教程 – 一站式学习Java网络编程视频教程 全面理解BIO(无密) 全面理解BIO/NIO/AIO 网络层编程,是每一个开发者都要面对的技术.课程为解决大家学习网络层知识的难题, ...

  4. 云网络相关知识学习列表

    网络相关知识学习列表 介绍 学习计算机网络相关知识的的技术文档 基础知识 1. 包括TCP/IP知识点 2. UDP协议 3. leaf-spine架构 4. IPv6 5. 大二层网络 6. VLA ...

  5. (pytorch-深度学习系列)ResNet残差网络的理解-学习笔记

    ResNet残差网络的理解 ResNet伴随文章 Deep Residual Learning for Image Recognition 诞生,该文章是MSRA何凯明团队在2015年ImageNet ...

  6. 网络相关的常用协议总结

    软件:实现某些功能的程序. 硬件:看的见摸的着的,比如硬盘,CPU.它们是软件运行和实现功能的载体. 网络:按一定的通信协议,由网络硬件(如路由,服务器,网线,终端机等)组成的能实现数据流通的硬件架构 ...

  7. Unity C# 网络学习(十二)——Protobuf生成协议

    Unity C# 网络学习(十二)--Protobuf生成协议 一.安装 去Protobuf官网下载对应操作系统的protoc,用于将.proto文件生成对应语言的协议语言文件 由于我使用的是C#所以 ...

  8. nmap扫描失败_网络协议arp学习和网络扫描

    0x00  ARP概述 中文名: 地址解析协议(英语:Address Resolution Protocol,缩写:ARP)是通过解析网络层地址(IPv4,IPv6)来寻找数据链路层地址的一个在网络中 ...

  9. 【网络基础概念】: 网络相关硬件、TCP/IP四层协议模型、OSI七层协议模型。

    # 时人不识凌云木,直待凌云始道高 # 大家好,我是码辣,是一只正在努力的小小猿一枚,希望大家多多关照 ^v^. # 初次见面,希望大家能够喜欢.(如果你认为文章可以,别忘一键三连呀!嘿嘿. # 有什 ...

最新文章

  1. jQuery之get方法
  2. manager的烦恼
  3. android事件处理概括
  4. 基于WinSvr2016(TP)构建的“超融合技术架构”进阶篇
  5. Nacos源码集群一致性
  6. Linux云服务器安装Redis并设置远程连接设置开机自启
  7. angularjs 元素重复指定次数_[LeetCode] 442. 数组中重复的数据
  8. php parse url 中文,php parse_url()函数解析URL用法总结
  9. [转载] 中华典故故事(孙刚)——01 天要下雨_娘要嫁人
  10. [转]Delphi的运算符重载
  11. Julia: 引用、copy与数组
  12. SATA硬盘有固件问题的硬盘型号以及购买建议
  13. 阅读多篇面经,总结了10个面试官常问的项目问题
  14. anchor和正负样本
  15. 手机老是收不到短信验证码?我来告诉你为什么!
  16. 最受玩家喜爱的十大游戏IP类型,你最喜欢哪个?
  17. unity-摄像机跟随
  18. selenium常用的浏览器窗口操作
  19. 济宁市计算机技能大赛,济宁市教育局 文件公告 关于举办济宁市第十届中小学电脑机器人竞赛活动的通知...
  20. 申购新股流程|申购新股流程介绍

热门文章

  1. Window 远程桌面漏洞风险,各个厂家的扫描修复方案(CVE-2019-0708)
  2. 《python灰帽子》笔记四
  3. 视频服务器(8) Kurento[3] unity客户端
  4. 我的2016--一半欢喜一半愁,生活总在起变化
  5. Python脚本制作exe程序超详细!
  6. cad画不规则实体_如何在CAD中徒手画不规则的图形
  7. JavaScript原型详解(通俗易懂)
  8. 计算机科学期刊是ISTP吗,ISTP期刊是核心期刊吗
  9. 分枝定界图解(含 Real-Time Loop Closure in 2D LIDAR SLAM论文部分解读及BB代码部分解读)
  10. SQL左连接副表取最新的一条记录的多中方式