目录
1、说明
我只是进行了摘录,详情可以看原文:
https://www.cnblogs.com/huansky/p/13951567.html
2、HTTP特点
2.1、灵活可扩展
这里的灵活可扩展,指的是HTTP刚开始的时候,只是规定了用空格来分割单词、用换行来分割header-body等报文的基本格式;
至于HTTP里面填写什么,则由开发者任意定制,后续就慢慢添加了请求方法、版本号、状态码、头字段等特性,而body也不再限于文本形式,也能够传输图片、音频视频等任意数据;
后续的RFC文档,就把这些已经形成的默认惯例加以标准化;
2.2、可靠传输
HTTP是基于TCP/IP协议来完成的,所以HTTP也就继承了可靠传输的特性;
2.3、应用层协议
HTTP协议是一个应用层的协议
2.4、请求-应答模式
HTTP协议使用的是请求-应答通信模式,该模式是请求方先主动发起连接和请求,应答方只有在被动收到请求后才能答复,如果没有请求时则不会有任何动作;
2.5、无状态
“状态”其实就是客户端或者服务器里保存的一些数据或者标志,记录了通信过程中的一些变化信息;
HTTP在整个协议里没有规定任何的“状态”,客户端和服务器永远是处在一种“无知”的状态。建立连接前两者互不知情,每次收发的报文也都是互相独立的,没有任何的联系;
3、连接管理
3.1、短连接
在HTTP 协议(0.9/1.0)版本时,要求每次发送请求前需要先与服务器建立连接,收到响应报文后会立即关闭连接;
但是,由于HTTP协议是基于TCP/IP,由于TCP建立连接时需要“三次握手”,关闭连接时需要“四次挥手”,导致大量的时间全部浪费在TCP建立连接、关闭连接上;
因为客户端与服务器的整个连接过程很短暂,不会与服务器保持长时间的连接状态,所以就被称为“短连接”;
3.2、长连接
针对短连接暴露出的缺点,HTTP协议就提出了“长连接”的通信方式,其解决办法也很简单,既然TCP连接和关闭非常耗时间,那么就把这个时间成本由原来的一个请求-应答均摊到多个请求-应答上,即建立TCP连接之后,多次发送HTTP请求-响应,N个HTTP请求-响应结束之后,TCP关闭连接;
3.3、长连接缺点
HTTP/1.1中的连接都会默认启用长连接,不需要用什么特殊的头字段指定,只要向服务器发送了第一次请求,后续的请求都会重复利用第一次打开的TCP连接,也就是长连接;
也可以在请求头里明确地要求使用长连接机制,使用“Connection: keep-alive”字段,但是因为TCP连接长时间不关闭,服务器必须在内存里保存它的状态,这就占用了服务器的资源。如果有大量的空闲长连接只连不发,就会很快耗尽服务器的资源,导致服务器无法为真正有需要的用户提供服务,所以,长连接也需要在恰当的时间关闭,不能永远保持与服务器的连接,客户端可以在请求头里加上“Connection: close”字段,告诉服务器:“这次通信后就关闭连接”,服务器看到这个字段,就知道客户端要主动关闭连接;
4、GET与POST常见误解
从上面总结可以知道,HTTP底层用的是TCP/IP协议,而method=get与method=post只是HTTP的某个属性而已;
理论上来讲,当method=get时,你可以在URL中拼接无数个参数,但这样会带来性能风险,因此,大多数浏览器通常都会限制URL长度在2K个字节,而大多数服务器最多处理64K大小的URL;
至于超过规定长度的部分,一概舍弃,至于当method=get时在request body中添加的数据,不同服务器的处理方式也是不同的,有的会读取,而有的直接忽略;
因此,我们可以得知,不同浏览器/服务器,对GET请求中URL参数长度有不同的要求;
5、TCP的连接与关闭
5.1、TCP连接大概流程
①应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(受数据链路层的最大传输单元(MTU)的限制);
②TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层;
③TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收;
④然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传;
⑤TCP用一个校验和函数来检验数据是否有错误;
⑥在发送和接收时都要计算校验和。
5.2、TCP消息头

(图片来自百度百科)
①Source Port/Destination Port
源/目标端口号字段,分别占16比特,其实,端口号就是我们所说的应用程序,例如:MySQL的3306,Tomcat的8080,FTP的21等等,操作系统一共可以分配0~65535之间的任何数字;
②Sequence Number
顺序号字段,占32比特,用来标识从TCP源端向TCP目标端发送的数据字节流,在TCP传送的流中,每一个字节一个顺序号,通过序号来确保接受完整,同时序号也保证了传送到接收端实体的包的按序接收;(每一个字节一个顺序号,而顺序号字段占32bit,2^32 = 4294967296个序号,而1B = 8b,1B * 4294967296 =4GB)
③Acknowledgment Number
确认号字段,占32比特,只有ACK标志为1时,确认号字段才有效,它包含目标端所期望收到源端的下一个数据字节,它是对接收到的数据的最高序列号的确认,并向发送端返回一个下次接收时期望的TCP数据包的序列号(Ack Number)。例如,主机A发送的当前数据序号是400,数据长度是100,则接收端收到后会返回一个确认号是501的确认号给主机A。
④Data Offset
头部长度字段,占4比特,标识该头部占多少个32比特,当没有任何选项字段时,TCP头部长度为20字节,最多时可以有60字节的TCP头部,这是因为4位首部长度字段所能表示的最大值为1111,转化为十进制后为15,15*32/8 = 60B,故报头最大长度为60字节;
⑤标志位字段
占6比特,各比特的含义如下:
URG:紧急指针标志,为1时表示紧急指针有效,为0则忽略紧急指针;
ACK:确认序号标志,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段;
PSH:push标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队;
RST:重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接,或者用于拒绝非法的报文段和拒绝连接请求;
SYN:同步序号,用于建立连接过程,在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1;
FIN:finish标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流;
⑥Window
窗口大小字段,占16比特,用来进行流量控制,单位为字节数,这个值是本机期望一次接收的字节数,即告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度;
⑦Checksum
TCP校验和字段,占16比特。对整个TCP报文段,即TCP头部和TCP数据进行校验和计算,并由目标端进行验证,由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏;
⑧Urgent Pointer
紧急指针字段,占16比特,它是一个偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号,因此,这个字段是紧急指针相对当前序号的偏移,不妨称之为紧急偏移。TCP的紧急指针是发送端向接收端发送紧急数据的方法;
⑨Options/Padding
选项和填充,最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍;
⑩data
数据部分,TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有TCP首部;如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据;在处理超时的许多情况中,也会发送不带任何数据的报文段;
5.3、TCP的3次握手
第一次握手
建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;
备注:SYN即同步序列编号(Synchronize Sequence Numbers)。
第二次握手
服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入 SYN_RECV状态;
第三次握手
客户端收到服务器的SYN + ACK包,向服务器发送确认包 ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手;

注意:
①大写的SYN和ACK,指的是“标志位字段”,取值范围要么是1,要么是0;
②小写的seq和ack,指的是32位比特的顺序号字段、确认号字段;
5.4、TCP的4次挥手
第一次挥手
客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为 seq=u(等于前面已经传送过来的数据的最后一个字节的序号加 1),此时,客户端进入 FIN-WAIT-1(终止等待1)状态。 FIN报文段即使不携带数据,也要消耗一个序号;
第二次挥手
服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号 seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间;
客户端收到服务器的确认请求后,此时,客户端就进入 FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据);
第三次挥手
服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为 seq=w,此时,服务器就进入了 LAST-ACK(最后确认)状态,等待客户端的确认;
客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是 seq=u+1,此时,客户端就进入了 TIME-WAIT(时间等待)状态。注意此时 TCP连接还没有释放,必须经过 2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入 CLOSED 状态;
第四次挥手
服务器只要收到了客户端发出的确认,立即进入 CLOSED 状态。同样,撤销 TCB 后,就结束了这次的 TCP 连接。可以看到,服务器结束 TCP 连接的时间要比客户端早一些;

注意:
①大写的FIN和ACK,指的是“标志位字段”,取值范围要么是1,要么是0;
②小写的seq和ack,指的是32位比特的顺序号字段、确认号字段;
5.5、为什么连接时是三次握手,而不是两次握手?
第一次握手时
Client不知道链路通不通,什么都不能确定;
Server收到后则能确认Client发送正常;
第二次握手时
Client能确认自己端发送/接收正常,Server端发送/接收正常;
Server则能确认己方接收正常 ,Client发送正常;
第三次握手时
Client能确认己方发送/接收正常, Server发送/接收正常;
Server则能确认己方发送/接收正常,Client发送/接收正常;
因此,如果是2次握手的话,Server无法确定Client的接收功能是否正常,如果Server在无法确定Client的接收正常工作的情况下,就发送各种业务数据,鬼知道Client会不会收到数据,说不定网络原因无法收到,而Client还在苦苦等待Server的报文;
5.6、TCP状态图

CLOSED:状态时初始状态;
LISTEN:被动打开,Server端的状态变为LISTEN (监听),注意这里是被动打开,其概念是:主动连接的一方的应用程序通知被动连接一方的操作系统,希望建立一个传入的连接,为此,被动连接的一方的操作系统为此与主动连接的一方建立一个连接;
SYNRECVD:服务器端收到SYN后,状态为SYN并发送SYN ACK;
SYN_SENTY:应用程序发送SYN后,状态为SYN_SENT;
ESTABLISHED:SYNRECVD收到ACK后,状态为ESTABLISHED; SYN_SENT在收到SYN ACK并发送ACK后,状态为ESTABLISHED;
CLOSE_WAIT:服务器端在收到FIN后,发送ACK,状态为 CLOSE_WAIT;如果此时服务器端还有数据需要发送,那么就发送,直到数据发送完毕;此时,服务器端发送FIN,状态变为LAST_ACK;
FIN_WAIT_1:应用程序端发送FIN,准备断开TCP连接;状态从 ESTABLISHED->FIN_WAIT_1;
FIN_WAIT_2:应用程序端只收到服务器端得ACK信号,并没有收到FIN信号;说明服务器端还有数据传输,那么此时为半连接;
TIME_WAIT:是为了实现TCP全双工连接的可靠性关闭,用来重发可能丢失的ACK报文;这里需要持续2个MSL(最大报文生存时间):
有两种方式进入该状态:
①FIN_WAIT_1进入:此时应用程序端口收到 FIN+ACK(而不是像 FIN_WAIT_2 那样只收到 ACK,说明数据已经发送完毕)并向服务器端口发送 ACK;
②FIN_WAIT_2进入:此时应用程序端口收到了FIN,然后向服务器端发送ACK;
5.7、为什么Client端要等待2个MSL时间?
当Client在第4次挥手发送ACK报文时,如果Server端在规定的时间内没有收到该报文,则Server端会继续重发第3次挥手的FIN报文,当Client端收到重发的FIN报文后,则继续重发ACK报文,直到Server端收到ACK报文,然后Client端在2个MSL时间内也没收到FIN报文,则代表Server端收到ACK报文,这次TCP正常关闭;
综上所述,Client端必须确保当前端口始终参与当前TCP断开连接的操作,不能去干其他事情,因此,在TIME_WAIT状态下Client和Server端的端口都不能使用,必须等到2个MSL时间结束才可继续使用,否则的话,Client端该端口参与下一个TCP建立连接的操作时,一会儿收到了FIN报文,你说Client到底怎么处理,而Server还在苦苦等待ACK报文来正常终结TCP断开;
5.8、FIN_WAIT_2状态特点
半关闭状态
在关闭连接时,客户端和服务器两次握手之后的状态。在这个状态下,Client还有接受Server数据的能力,但是已经无法发送数据,但也有一种可能是,客户端一直处于FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态,而直到应用层来决定关闭这个状态;
5.9、TCP建立连接后,Client突然中断后怎么办?
TCP设有一个保活计时器,Client如果出现故障,服务器不会一直等下去,服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若2小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次,若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接;
172万+

被折叠的 条评论
为什么被折叠?



