TCP/UDP/HTTP/HTTPS

TCP/UDP

TCP

图片来源

tcp报文格式

三次握手

tcp三次握手示意图

三次握手流程:

最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。

  1. TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;

  2. TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号

  3. TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号

  4. TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号

  5. 当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。

为何不采用两次握手

将三次握手改成两次握手可能发生死锁。主机s和c之间要建立通讯。s将请求报文发送给c , 此后c发送链接确认报文,但报文再网络中丢失了。此时c认为已经建立链接了,开始发送数据分组,但s认为还未建立链接将拒绝s的数据报文,只等待链接确认报文。c没有收到后续的报文则认为报文再网络中丢失了或者拥塞住s没有收到报文,则重传数据报文。形成了死锁

四次挥手

四次挥手流程:

数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。

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

  2. 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

  3. 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)

  4. 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

  5. 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗ *∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

  6. 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

为何需要进入TIME-WAIT等待 2 MSL 时间才进入close状态

  1. 保证TCP协议的全双工连接能够可靠关闭

    如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

  2. 保证这次连接的重复数据段从网络中消失

    如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失

为何握手需要三次而挥手需要四次

握手中建立连接时SYN + ACK 可以一起发送,而挥手的时候可能数据没有完全传送完成,只进行ACK确认,不进行FIN关闭

三次握手和四次挥手简单举例

三次握手

听的到吗 ? 我听得到 , 你呢 ? 我也听得到 。 开始后续对话

四次挥手

老师,下课了。 我知道了,我说完这一点。我说完了,好了,下课。 我知道了。

文件重传

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

UDP

报文格式

UDP报文首部

图片来源

  • 源端口(Source port)和目的端口(Destination port)

  • 报文长度(Length)

    16 bits,指示UDP报文(首部和数据)的总长度。最小8 bytes,只有首部,没有数据。最大值为65535 bytes。实际上,由于IPv4分组的最大数据长度为(65535 - 20 = 65515) bytes,UDP的报文长度不超过65515 bytes。IPv6允许UDP的长度超过65535,此时length字段设为0。

  • 校验和(Checksum)

HTTP报文格式

http请求报文

HTTP的请求报文包括:请求行(request line)请求头部(header)空行请求数据(request data) 四个部分组成。

图片来源

img

GET /admin_ui/rdx/core/images/close.png HTTP/1.1
Accept: /
Referer: http://xxx.xxx.xxx.xxx/menu/neo
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: xxx.xxx.xxx.xxx
Connection: Keep-Alive
Cookie: startupapp=neo; is_cisco_platform=0; rdx_pagination_size=250%20Per%20Page; SESSID=deb31b8eb9ca68a514cf55777744e339

请求行包括: 请求方法,URL(包括参数信息),协议版本这些信息(GET /admin_ui/rdx/core/images/close.png HTTP/1.1)

请求头部(Header)是一个个的key-value值,比如

  • Accept-Encoding: gzip, deflate

  • User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)

  • 空行(CR+LF):请求报文用空行表示header和请求数据的分隔

请求数据:GET方法没有携带数据, POST方法会携带一个body

http响应报文

HTTP的响应报文包括:状态行,响应头,空行,数据(响应体)

图片来源

img

HTTP/1.1 200 OK
Bdpagetype: 1
Bdqid: 0xacbbb9d800005133
Cache-Control: private
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html
Cxy_all: baidu+f8b5e5b521b3644ef7f3455ea441c5d0
Date: Fri, 12 Oct 2018 06:36:28 GMT
Expires: Fri, 12 Oct 2018 06:36:26 GMT
Server: BWS/1.1
Set-Cookie: delPer=0; path=/; domain=.baidu.com
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=0; path=/
Set-Cookie: H_PS_PSSID=1433_21112_18560_26350_27245_22158; path=/; domain=.baidu.com
Vary: Accept-Encoding
X-Ua-Compatible: IE=Edge,chrome=1
Transfer-Encoding: chunked

状态行包括:HTTP版本号,状态码和状态值组成。

响应头类似请求头,是一系列key-value值

  • Cache-Control: private

  • Content-Encoding: gzip

  • Server: BWS/1.1

  • Set-Cookie: delPer=0; path=/; domain=.baidu.com

空白行:同上,响应报文也用空白行来分隔header和数据

响应体:响应的data,本例中是一段HTML

常见状态码

数字中的第一位指定了响应类别,后两位无分类,响应类别有一下5种:

状态码分类表

类别 原因短语
1xx Informational(信息性状态码) 接受的请求正在处理
2xx Success(成功状态码) 请求正常处理完毕
3xx Redirection(重定向) 需要进行附加操作以完成请求
4xx Client error(客户端错误) 客户端请求出错,服务器无法处理请求
5xx Server Error(服务器错误) 服务器处理请求出错

14种常见状态码

2xx (3种)

  • 200 OK:表示从客户端发送给服务器的请求被正常处理并返回

  • 204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);

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

3xx (5种)

  • 301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;

  • 302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;

301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)

  • 303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;

302与303的区别:后者明确表示客户端应当采用GET方式获取资源

  • 304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;

  • 307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);

4xx (4种)

  • 400 Bad Request:表示请求报文中存在语法错误;

  • 401 Unauthorized:未经许可,需要通过HTTP认证;

  • 403 Forbidden:服务器拒绝该次访问(访问权限出现问题)

  • 404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;

5xx (2种)

  • 500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;

  • 503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;

HTTP一次请求过程

  • 建立 TCP链接(可能会进行一次DNS域名解析)

  • 三次握手完成后,客户端向服务器发送请求命令,比如: GET https://www.baidu.com?name=xx&addr=xx HTTP1.1

  • 客户端发送请求头信息,发送玩header后会接着发送一个空白行,get请求没有数据,post请求要发送body数据

  • 服务器接收到以上信息后,开始处理业务,处理完业务后,服务器开始应答

  • 服务器返回响应头信息,发送完response header 后再发送一个空白行

  • 然后服务器向客户端发送数据

  • 发送完数据后,服务器四次挥手关闭会话

HTTP 1.0 、HTTP 1.1和HTTP 2

版本 内容
http 1.0 传输内容格式不限制,增加PUT、PATCH、HEAD、 OPTIONS、DELETE命令
http 1.1 持久连接(长连接)、节约带宽、HOST域、管道机制、分块传输编码
http 2 多路复用、服务器推送、头信息压缩、二进制协议等

HTTP 1.0 和 HTTP 1.1的区别

1.1 长连接(Persistent Connection) HTTP1.1支持长连接和请求的流水线处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启长连接keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。HTTP1.0需要使用keep-alive参数来告知服务器端要建立一个长连接。

1.2 节约带宽 HTTP1.0中存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能。HTTP1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,客户端接收到100才开始把请求body发送到服务器;如果返回401,客户端就可以不用发送请求body了节约了带宽。

1.3 HOST域 在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname),HTTP1.0没有host域。随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都支持host域,且请求消息中如果没有host域会报告一个错误(400 Bad Request)。

1.4缓存处理 在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。

HTTP 1.1 和 HTTP 2.0的区别

2.1 多路复用

HTTP2.0使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级。HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的。

图片来源

1.1和2比较

2.2 头部压缩

在HTTP1.1中,HTTP请求和响应都是由状态行、请求/响应头部、消息主体三部分组成。一般而言,消息主体都会经过gzip压缩,或者本身传输的就是压缩过后的二进制文件,但状态行和头部却没有经过任何压缩,直接以纯文本传输。随着Web功能越来越复杂,每个页面产生的请求数也越来越多,导致消耗在头部的流量越来越多,尤其是每次都要传输UserAgent、Cookie这类不会频繁变动的内容,完全是一种浪费。

HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。

HTTPS

HTTP是明文传输,整个过程完全透明,任何人都能够在链路中截取、修改或者伪造请求,数据不具有可靠性。因此有了https

HTTPS是身披SSL外壳的HTTP。HTTPS是一种通过计算机网络进行安全通信的传输协议,经由HTTP进行通信,利用SSL/TLS建立全信道,加密数据包。HTTPS使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性。

https工作原理

SSL建立连接原理图
  1. 进行tcp三次握手链接

  2. 客户端将本机支持的加密算法发送给服务器

  3. 服务器在加密套件组件中选择一个认为可靠的加密套件,并将该信息和公钥信息相应给客户端

  4. 服务器验证证书,保证服务器是正常的而非黑客的服务器,(在建立链接的时候,可能截取dns信息,换成黑客的服务器信息)

  5. 客户端使用一个随机算法生成一个密钥并使用公钥加密,并发送给服务器

  6. 服务器使用私钥对加密过来的信息进行解密,得到密钥

  7. 后续使用密钥进行对称加密双向传输

参考:

https://juejin.im/entry/5981c5df518825359a2b9476

你可能感兴趣的:(TCP/UDP/HTTP/HTTPS)