HTTP 协议是以 ASCII 码进行传输的,创建在 TCP/IP 协议上的应用层规范。规范把 HTTP 分为三个部分:状态行、请求头、请求主体。HTTP 定义了与服务器交互的不一样方法,经常使用的有以下四种:GET
、POST
、DELETE
、PUT
。 URL 全称是资源描述符,一个 URL 地址用于描述一个网络上的资源,而 HTTP 中的 POST
、DELETE
、PUT
、GET
就对应着对这个资源的 增、删、改、查 四个操做。其余请求方式还有:HEAD
、 OPTIONS
、 TRACE
、 PATCH
。算法
GET
用于信息的获取。(安全和幂等)注:安全意味着该操做用于获取信息而非修改信息。幂等意味着对同一 URL 的多个请求应返回一样的结果。POST
表示可能修改服务器上的资源的请求。(非安全、非幂等)HEAD
与 GET
方法相似,但不返回 message body内容,仅仅是得到获取资源的部分信息(content-type、content-length)(安全和幂等)PUT
用于建立、更新资源。(非安全、幂等)DELETE
删除资源。(非安全、幂等)OPTIONS
用于 URL 验证,验证接口服务是否正常。(安全、幂等)TEACE
回显服务器收到的请求,这样客户端能够看到(若是有)哪一些改变或者添加已经被中间服务器实现.(安全、幂等)PATCH
用于建立、更新资源,于PUT相似,区别在于PATCH表明部分更新; 后来提出的接口方法,使用时可能去要验证客户端和服务端是否支持;(非安全、幂等)GET 提交的数据量受 URL 长度的限制,HTTP 协议没有对 URL 长度进行限制,这个限制是浏览器和服务器对他的限制;理论上 POST 也是没有大小限制的,HTTP 协议也没有进行大小限制,出于安全考虑,服务器会作必定的限制。编程
HTTP 协议中规定 POST 提交的数据必须在 Body 部分中,但协议并未规定数据须要采用何种数据格式或编码方式,服务端一般经过请求头中的 Content-Type
字段来获知请求中的消息主体是以何种方式编码,再对主体进行解析。 POST 提交数据的方案,包含:Content-Type 和消息主体编码方式两部分:json
application/x-www-form-urlencoded
:最多见的 POST 数据提交方式,浏览器的原生
multipart/form-data
:使用表单上传文件时,必须让表单的 enctype
等于 multipart/form-data
。这种方式通常用于上传文件。application/json
text/xml
application/x-protobuf
只要服务器能够根据 Content-Type 和 Content-Encoding 正确解析出请求便可。设计模式
HTTP 响应跟 HTTP 请求相似,也是由三部分构成:状态行、响应头、响应正文。 状态行由协议版本、数字形式的状态代码、响应的状态描述构成,各元素以空格分割。常见的状态码:浏览器
200 OK
客户端请求成功301 Moved Permanently
请求永久重定向302 Moved Temporarily
请求临时重定向304 Not Modified
文件未修改,能够直接使用缓存文件400 Bad Request
因为客户端请求有语法错误,没法被服务器所理解401 Unauthorized
请求未经受权(状态代码必须和WWW-Authenticate报头域一块儿使用)403 Forbidden
服务器收到请求,但拒绝提供服务。服务器一般会在响应正文中给出不提供服务的缘由。404 Not Found
请求的资源不存在。500 Internal Server Error
服务器发生不可预知的错误,致使没法完成客户端的请求。503 Service Unavailable
服务器当前不可处理客户端的请求,在一段时间后服务器可能会恢复正常。HTTP 条件 GET 是HTTP 协议为了减小没必要要的宽带浪费,提出的一种方案。 使用时机:客户端以前已经访问过该网站,并想再次访问。 使用方法:客户端向服务端发送一个包询问是否在上次访问网站后的时间后更改了页面,若是服务器没有更新,显然不须要把整个网页传给客户端,客户端只须要使用本地缓存便可,若是服务器对照客户端给出的时间已经更新了客户端请求的网页,则发送这个更新了的网页给用户。缓存
通常状况下,HTTP 协议采用“请求-应答”模式,当使用普通模式,即非 Keep-Alive 模式时,每一个请求/应答客户端和服务器都要新建一个链接,完成以后当即断开链接(HTTP 协议为无链接的协议);当使用 Keep-Alive 模式(又称持久链接、链接重用)时,Keep-Alive 功能使客户端到服务端的链接持续有效,当出现对服务器的后续请求时,Keep-Alive 功能避免了创建或者从新创建链接。 在 HTTP 1.0 中: 若是客户端浏览器支持 Keep-Alive,那么就在 HTTP 请求头中添加一个字段 Connection-Keep-Alive
。 在 HTTP 1.1 中:默认全部链接都被保持。安全
Keep-Alive: timeout=5, max=100
,表示这个TCP通道能够保持5秒,max=100,表示这个长链接最多接收100次请求就断开.Keep-Alive
没有改变这个结果,Keep-Alive
没法保证客户端和服务端的链接必定是活跃的,惟一能保证的是当链接被断开时将会收到一个通知。Content-Length
指示的大小,2.动态生成的文件没有 Content-Length ,它是分块传输(chunked),这时候就要根据 chunked 编码来判断,chunked 编码的数据在最后有一个空 chunked 块,代表本次传输数据结束.Transform-Encoding
是一个用来标明 HTTP 报文传输格式的头部值,当前的 HTTP 规范里只定义了一种传输格式 - chunked
. 若是一个 HTTP 消息请求或应答消息的 Transform-Encoding
消息头的值是 chunked ,那么消息体由数量未定的块组成,并以最后一个大小为 0 的块为结束。服务器
chunked
和 multipart
两个名词在乎义上有相似的地方,不过在 HTTP 协议当中这两个概念则不是一个类别的。multipart 是一种 Content-Type
,标示 HTTP 报文内容的类型,而 chunked
是一种传输格式,标示报头将以何种方式进行传输。chunked
传输不能事先知道传输内容的大小,只能靠最后的空 chunked
块来判断结束,因此对于下载请求,是没法知道下载进度的。chunked
优点在于服务端能够边生成内容边发送,无需事先知道所有内容。HTTP/2 是不支持 Transfer-Encoding: chunked
的,由于 HTTP/2 有本身的 streaming 传输方式:Source:MDN - Transfer-Encoding
默认状况下,HTTP 协议中每一个传输层链接只能承载一个 HTTP 请求和响应,浏览器会在收到上一个请求的响应以后再发送下一个请求。在使用持久链接的状况下,某个链接上消息的传递相似于: 请求1 -> 响应1 -> 请求2 -> 响应2 -> 请求3 -> 响应3
。 使用 HTTP Pipelining 是将多个 HTTP 请求打包传递的技术,在传送过程当中无需等待服务端的回应,某个链接上消息的传递相似于:请求1 -> 请求2 -> 请求3 -> 响应1 -> 响应2 -> 响应3
。微信
客户端打开与服务端的链接发送请求到服务端响应客户端请求的全过程称之为会话。cookie
会话跟踪是对同一个用户对服务器的连续的请求和接收响应的监视。
客户端跟服务端的通讯若是是采用 HTTP 协议通讯,而 HTTP 协议是无状态的,它没法保存用户的状态(信息),即一次响应后就断开了,下次请求须要从新链接,此时须要判断是否为同一个用户,因此须要会话跟踪技术实现这种需求。
如何防止 CSRF
跨站攻击:
Referer
Referer
中, 经过检查 Referer
的值,咱们就能够判断这个请求是合法的仍是非法的,可是问题出在服务器不是任什么时候候都能接受到 Referer
的值,因此 Referer Check
通常用于监控 CSRF
攻击的发生,而不用来抵御攻击。CSRF
攻击。若是防护 XSS: 将用户的输入使用 HTML 解析库进行解析,获取其中的数据。而后根据用户原有的标签属性,从新构建 HTML 元素树。构建的过程当中,全部的标签、属性都只从白名单中拿取。
HTTPS 即 HTTP over SSL/TLS ,是一种在加密通道进行 HTTP 内容传输的协议。
ClientHello
消息到服务端,消息中包含了它的 TLS (Transport Layer Security) 的版本、可用的加密算法和压缩算法。ServerHello
消息,消息中包含了服务端 TLS 的版本,服务端所选择的加密算法和压缩算法,以及数字证书认证机构(Certificate Authority,缩写 CA)签发的服务器公开证书,证书中包含了公钥。客户端会使用这个公钥来加密接下来的握手过程,直到协商生成一个新的对称密钥。证书中还包含了该证书所应用的域名范围(Common Name,简称 CN),用于客户端验证身份。finished
消息给服务端,使用对称密钥加密此次通讯的一个散列值。finished
消息,也使用协商好的对称密钥加密。TLS 的完整过程须要三个算法(协议),密钥交互算法、对称加密算法、消息认证算法
HTTPS 过程当中有一个很重要的步骤,就是服务器要有 CA 证书机构颁发的证书,客户端根据本身信任的 CA 列表验证服务器的身份。 现代浏览器中,证书的验证过程依赖于证书信任链:即一个证书须要依靠上一个证书来证实本身的可信的,最顶层的证书是根证书,拥有根证书的机构被称为 根 CA(通常操做系统自带)。
所谓中间人攻击,指攻击者与通讯的两端都创建独立的联系,并交换其所接受到的数据,使通讯的双方都认为他们正在经过私密的链接直接与对方进行通话,事实上整个会话都会被攻击者彻底控制。在中间人攻击中,攻击者能够拦截双方的通讯并插入新的内容。
SSL 剥离即阻止用户使用 HTTPS 访问网站。因为并非全部网站都只支持 HTTPS,大部分网站会同时支持 HTTP 和 HTTPS 两种协议。用户在访问网站时,也可能会在地址栏中输入 http://
的地址,第一次的访问彻底是明文的,这就给了攻击者可乘之机。经过攻击 DNS 响应,攻击者能够将本身变成中间人。
用于强制浏览器使用 HTTPS 访问网站的一种机制。它的基本机制是在服务器返回的响应中,加上一个特殊的头部,指示浏览器对于此网站,强制使用 HTTPS 进行访问。 HSTS 有一个很明显的缺点,是须要等待第一个服务器的影响中的头部才能生效,但若是第一次访问该网站就被攻击呢?为了解决这个问题,浏览器中会带上一些网站的域名,被称为 HSTS preload list。对于在这个 list 的网站来讲,直接强制使用 HTTPS。
HSTS 只解决了 SSL 剥离的问题,然而即便在全程使用 HTTPS 的状况下,咱们仍然有可能被监听。 第一步是须要攻击 DNS 服务器。第二步是攻击者本身的证书须要被用户信任,这一步对于用户来讲是很难控制的,须要证书颁发机构可以控制本身不滥发证书。
HPKP 技术是为了解决伪造证书攻击而诞生的。 HPKP(Public Key Pinning Extension for HTTP)在 HSTS 上更进一步,HPKP 直接在返回头中存储服务器的公钥指纹信息,一旦发现指纹和实际接受到的公钥有差别,浏览器就能够认为正在被攻击。 和 HSTS 相似,HPKP 也依赖于服务器的头部返回,不能解决第一次访问的问题,浏览器自己也会内置一些 HPKP 列表。
注意:TCP 并不能保证数据必定会被对方接收到,由于这是不可能的。TCP 能作到的是:若是有可能就把数据递送给对方,不然就通知用户(使用放弃重传并中断链接这一方式实现)。所以准确说 TCP 也不是 100% 可靠的协议,他所能提供的是数据的可靠递送或故障的可靠通知。
所谓三次握手,是指创建一个 TCP
链接,客户端和服务端须要传送三个包。 三次握手的目的是链接服务器指定端口,创建 TCP
链接,并同步链接双方的序列号和确认号,交换 TCP
窗口大小信息,在 socket
编程中,客户端执行 connect()
触发三次握手。
第一次握手:(SYN = 1,seq = x)
TCP
的 SYN
标志位置 1 的包,指明客户端须要链接的端口和初始序号 X, 保存在包头的序列号(Sequence Number)字段里。SYN_SEND
状态。第二次握手:(SYN = 1,ACK = 1,seq = y,ACKnum = x + 1)
SYN
和 ACK
均为 1,服务端选择本身的 ISN
序号,放到 seq
域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN
加1,即 X+1
SYN_RCVD
状态。第三次握手:(ACK = 1,ACKnum = y + 1)
SYN
标志位为 0,ACK
标志位为 1,而且把服务端发送的 ACK
的序号字段 + 1。ESTABLISHED
状态,当服务器端接收到这个包时,也进入 ESTABLISHED
状态,TCP
握手结束。三次握手示意图:
TCP
的拆除须要发送四个包,所以称为四次挥手,也叫改进的三次握手。客户端和服务端都可主动发起挥手动做,在 socket
编程中,任意一端执行 close()
便可产生挥手操做。
第一次挥手:(FIN = 1,seq = x)
FIN
标志位为 1 的包,表示本身没有数据可发送了,但仍能够接收数据。FIN_WAIT_1
状态。第二次挥手:(ACK = 1,ACKnum = x + 1)
FIN
包,并发送一个确认包,代表本身接收到了客户端关闭链接的请求,但尚未准备好关闭链接。CLOSE_WAIT
状态,客户端接收到这个确认包后,进入 FIN_WAIT_2
状态,等待服务端关闭链接。第三次挥手:(FIN = 1,seq = y)
FIN
置为 1。LAST_ACK
状态,等待来自客户端的最后一个 ACK
。第四次挥手:(ACK = 1,ACKnum = y + 1)
TIME_WAIT
状态。等待可能出现的要求重传的 ACK
包.CLOSED
状态。ACK
,觉得服务端已经正常关闭链接,因而本身也关闭链接,进入 CLOSED
状态。四次挥手示意图:
SYN
攻击?在三次握手过程当中的第二次握手时,服务器发送 SYN_ACK
以后,收到客户端的 ACK
以前的 TCP
链接称为半链接。此时服务器处于 SYN_RCVD
状态,当收到 ACK
后,服务器才能转入 ESTABLISHED
状态。 SYN
攻击指的是,"攻击客户端" 在短期内伪造大量不存在的 IP 地址,向服务端不断地发送 SYN
包,服务器回复确认包,并等待客户的确认。因为源地址是不存在的,服务器须要不断的重发直至超时,这些伪造的 SYN
包将长时间占用未链接队列,正常的 SYN
请求被丢弃,致使目标系统运行缓慢,严重者会引发网络堵塞甚至系统瘫痪。 SYN
攻击是一种典型的 Dos/DDos
攻击
SYN
攻击?当服务器出现大量的半链接状态时,特别是源 IP 地址是随机的,基本能够判定这是一次 SYN
攻击。在 Linux/Unix
上可使用系统自带的 netstats
命令来检测 SYN
攻击。
SYN
攻击?SYN
攻击不能彻底被阻止,除非将 TCP
协议从新设计。能够尽量减轻 SYN
攻击的危害:
SYN cookie
技术TCP 的链接,其实是一种纯软件层面的概念,在物理层并无“链接”这种概念。若是出现一些意外致使某端出现异常而另外一端没法感知,一直维护着这个链接,长时间会致使很是多的半链接状态的 TCP 链接,形成端系统资源的消耗和浪费,为了解决这个问题,在传输层能够利用 TCP 的 KeepAlive 机制来避免。
TCP KeepAlive 的基本原理:隔一段时间给链接对端发送一个探测包,若是收到对方回应的 ACK,则认为链接仍是存活的,在超过必定重试次数以后仍是没有收到对方的回应,则丢弃该 TCP 链接。
TCP KeepAlive 的局限:首先 TCP KeepAlive 检测的方式是发送一个 probe 包,会给网络带来额外的流量,另外 TCP KeepAlive 只能再内核层级检测链接的存活与否,而链接的存活不必定表明服务可用,例如当一个服务器 CPU 占用 100% 已经卡死不能响应请求了,此时 TCP KeepAlive 依然会认为链接是存活的。所以 TCP KeepAlive 对于应用层程序的价值是相对较小的。
UDP
是一个简单的传输层协议,和 TCP
相比,UDP
有以下几个显著的特性:
UDP
缺少可靠性。UDP
自己不提供确认序列号、超时重传等机制。UDP
数据报可能在网络中被复制,被从新排序。即 UDP
不保证数据报会到达其最终目的地,也不保证各个数据报的前后顺序,也不保证每一个数据报只到达一次。UDP
数据报是有长度的。每一个 UDP
数据报都有长度,若是一个数据报正确地到达目的地,那么该数据报的长度将随数据一块儿传递给接收方。而 TCP
是一个字节流协议,没有任何协议上的记录边界。UDP
是无链接的。UDP
客户端和服务器之间不存在长期的关系,UDP
发送数据报以前也不须要通过握手建立链接的过程UDP
支持多播和广播。IP 协议位于 TCP/IP 协议的第三层 - 网络层。与传输层协议相比,网络层的责任是提供点到点的服务,而传输层(TCP/UDP)则提供端到端的服务。
- | - |
---|---|
7 | 应用层 |
6 | 表示层 |
5 | 会话层 |
4 | 传输层 |
3 | 网络层 |
2 | 数据链路层 |
1 | 物理层 |
广播与多播仅用于 UDP(TCP 是面向链接的)
一共有四种广播地址:
255.255.255.255
,又称组播,使用 D 类地址,D类地址分配的 28bit 均用做多播组号而再也不表示其余
边界网关协议(BGP)是运行于 TCP 上的一种自治系统的路由协议
Socket 是对 TCP/IP 协议族的一种封装,是应用层与 TCP/IP 协议族通讯的中间软件抽象层。从设计模式的角度看,Socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Socket 接口后面,对用户来讲,一组简单的接口就是所有,让 Socket 去组织数据,以符合指定的协议。 Socket 还能够认为是一种网络间不一样计算机上的进程通讯的一种方法,利用三元组(IP 地址、协议、端口)就能够惟一标识网络中的进程,网络中的进程通讯能够利用这个标志与其余进程进行交互。 Socket 起源于 Unix,Unix/Linux 基本哲学之一就是:一切皆文件,均可以用“打开(open)-> 读写(write/read)-> 关闭(close)”模式来进行操做,所以 Socket 也被处理为一种特殊的文件。
一个简单的 Server 的流程包括:
大致的程序与调用的函数逻辑:
socket()
建立套接字bind()
分配套接字地址listen()
等待链接请求accept()
容许链接请求read()/write()
数据交换close()
关闭链接一个没有鸡汤只有干货的公众号