osi七层模型
物理层
首先解决两台物理机之间的通信需求,具体就是机器a往机器b发送比特流,机器b能收到比特流。
物理层主要定义了物理设备的标准,如网线的类型,光纤的接口类型,各种传输介质的传输速率。主要作用是传输比特流(0101二进制数据),将比特流转化为电流强弱传输,到达目的后再转化为比特流,即常说的数模转化和模数转换。这层数据叫做比特。网卡工作在这层。
物理层是osi七层模型的物理基础,没有它就谈不上数据传输了
物理层就是由实物所承载的,所以作比喻的话,公路、汽车和飞机等承载货物(数据)的交通工具,就是物理层的象征
数据链路层
在传输比特流的过程中,会产生错传、数据传输不完整的可能。
数据链路层定义了如何格式化数据进行传输,以及如何控制对物理介质的访问。通常提供错误检测和纠正,以确保数据传输的准确性。本层将比特数据组成帧,交换机工作在这层,对帧解码,并根据帧中包含的信息把数据发送到正确的接收方。
该层负责物理层面上互连的节点之间的通信传输。例如与1个以太网相连的两个节点间的通讯。常见的协议有 hdlc、ppp、slip 等
数据链路层会将0、1序列划分为具有意义的数据帧传送给对端(数据帧的生成与接收)
举个例子:暂且把需要传输的数据看作为不同来源的水,如果直接倒入池子中时,是无法重新分辨出不同来源的水的。但如果将不同来源的灌入瓶子中并打上记号,那就能区分出不同来源的水。这也就是为什么要划分为具有意义的数据帧传送给对端。同时要注意的是,数据链路层只负责将数据运送给物理相连的两端,并不负责直接发送到最终地址
网络层
随着网络节点的不断增加,点对点通讯需要通过多个节点,如何找到目标节点,如何选择最佳路径成为首要需求。
网络层主要功能是将网络地址转化为对应的物理地址,并决定如何将数据从发送方路由到接收方。网络层通过综合考虑发送优先权、网络拥塞程度、服务质量以及可选路由的花费来决定从一个网络中节点a到另一个网络中节点b的最佳路径。由于网络层处理并智能指导数据传送,路由器连接网络隔断,所以路由器属于网络层。此层的数据称之为数据包。本层需要关注的协议tcp/ip协议中的ip协议。
网络层负责将数据传输到目标地址。目标地址可以使多个网络通过路由器连接而成的某一个地址。因此这一层主要负责寻址和路由选择。主要由 ip、icmp 两个协议组成
网络层将数据从发送端的主机发送到接收端的主机,两台主机间可能会存在很多数据链路,但网络层就是负责找出一条相对顺畅的通路将数据传递过去。传输的地址使用的是ip地址。ip地址通过不断转发到更近的ip地址,最终可以到达目标地址
传输层
随着网络通信需求的进一步扩大,通信过程中需要发送大量的数据,如海量文件传输,可能需要很长时间,网络在通信的过程中会中断很多次,此时为了保证传输大量文件时的准确性,需要对发送出去的数据进行切分,切割为一个一个的段落(segement)发送,其中一个段落丢失是否重传,段落是否按顺序到达,是传输层需要考虑的问题。
传输层解决了主机间的数据传输,数据间的传输可以是不同网络,并且传输层解决了传输质量的问题。
传输层需要关注的协议有tcp/ip协议中的tcp协议和udp协议。
会话层
自动收发包,自动寻址。
会话层作用是负责建立和断开通信连接,何时建立,断开连接以及保持多久的连接。常见的协议有 adsp、rpc 等
表示层
linux给windows发包,不同系统语法不一致,如exe不能在linux下执行,shell不能在windows不能直接运行。于是需要表示层。
解决不同系统之间通信语法问题,在表示层数据将按照网络能理解的方案进行格式化,格式化因所使用网络的不同而不同。
它主要负责数据格式的转换。具体来说,就是讲设备固有的数据格式转换为网络标准格式。常见的协议有 ascii、ssl/tls 等
应用层
规定发送方和接收方必须使用一个固定长度的消息头,消息头必须使用某种固定的组成,消息头中必须记录消息体的长度等信息,方便接收方正确解析发送方发送的数据。
应用层旨在更方便应用从网络中接收的数据,重点关注tcp/ip协议中的http协议
osi七层网络模型 |
tcp/ip四层概念模型 |
对应网络协议 |
应用层(application) |
应用层 |
http、tftp, ftp, nfs, wais、smtp |
表示层(presentation) |
telnet, rlogin, snmp, gopher |
|
会话层(session) |
smtp, dns |
|
传输层(transport) |
传输层 |
tcp, udp |
网络层(network) |
网络层 |
ip, icmp, arp, rarp, akp, uucp |
数据链路层(data link) |
数据链路层 |
fddi, ethernet, arpanet, pdn, slip, ppp |
物理层(physical) |
ieee 802.1a, ieee 802.2到ieee 802.11 |
ip、tcp、udp、http等都属于tcp/ip协议,tcp/ip泛指这些协议。
osi模型注重通信协议必要的功能;tcp/ip更强调在计算机上实现协议应该开发哪种程序
tcp与udp区别总结:
1、tcp面向连接(如打电话要先拨号建立连接);udp是无连接的,即发送数据之前不需要建立连接
2、tcp提供可靠的服务。也就是说,通过tcp连接传送的数据,无差错,不丢失,不重复,且按序到达;udp尽最大努力交付,即不保证可靠交付
3、tcp面向字节流,实际上是tcp把数据看成一连串无结构的字节流;udp是面向报文的
udp没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如ip电话,实时视频会议等)
4、每一条tcp连接只能是点到点的;udp支持一对一,一对多,多对一和多对多的交互通信
5、tcp首部开销20字节;udp的首部开销小,只有8个字节
6、tcp的逻辑通信信道是全双工的可靠信道,udp则是不可靠信道
端口:两个进程在计算机内部进行通信,其中两个进程通信最基本的前提是唯一标识一个进程,通过唯一标识找到对应的进程。在本地进程通信中可以通过pid,但pid只在本地唯一。
如果把两个进程放到两台计算机通信,pid实现不了。解决这个问题的方法就是在传输层使用协议端口号,简称端口。ip地址可以唯一标识主机,tcp协议和端口号可以唯一标识主机中的一个进程,利用ip地址 协议 端口号唯一标识去标识网络中的一个进程,这种唯一标识的模式称为socket。
源端口号和目地端口各占16位两个字节,也就是端口的范围是2^16=65535
另外1024以下是系统保留的,从1024-65535是用户使用的端口范围
seq序号:占4字节,tcp连接中传送的字节流中的每个字节都按顺序编号。例如:一段报文的序号字段值是107,携带的数据是100个字段,下一个报文段序号从107 100=207开始。
ack确认号:4个字节,是期望收到对方下一个报文段的第一个数据字节的序号。例如:b收到a发送的报文,其序号字段是301,数据长度是200字节,表明b正确收到a发送的到序号500为止的数据(301 200-1=500),b期望收到a下一个数据序号是501。b发送给a的确认报文段中把ack确认号置为501。
数据偏移:头部有可选字段,长度不固定,指出tcp报文段的数据起始处距离报文段的起始处有多远。
保留:保留今后使用的,被标为1。
控制位:由8个标志位组成。每个标志位表示一个控制功能。
其中主要的6个:
urg紧急指针标志,为1表示紧急指针有效,为0忽略紧急指针。
ack确认序号标志,为1表示确认号有效,为0表示报文不含确认信息,忽略确认号字段。上面的确认号是否有效就是通过该标识控制的。
psh标志,为1表示带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将该报文段交给应用程序,而不是在缓冲区排队。
rst重置连接标志,重置因为主机崩溃或其他原因而出现错误的连接,或用于拒绝非法的报文段或非法的连接。
syn同步序号,用于建立连接过程,在连接请求中syn=1和ack=0表示该数据段没有使用捎带的确认域,连接应答捎带一个确认即syn=1和ack=1。
fin终止标志,用于释放连接,为1时表示发送方没有发送了。
窗口:滑动窗口大小,用来告知发送端接收端缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。
校验和:奇偶校验,此校验和是对整个的tcp报文段(包括tcp头部和tcp数据),以16位进行计算所得,由发送端计算和存储,接收端进行验证。
紧急指针:只有控制位中的urg为1时才有效。指出本报文段中的紧急数据的字节数。
选项:其长度可变,定义其他的可选参数。
udp报文中每个字段的含义如下:
- 源端口:这个字段占据 udp 报文头的前 16 位,通常包含发送数据报的应用程序所使用的 udp 端口。接收端的应用程序利用这个字段的值作为发送响应的目的地址。这个字段是可选的,所以发送端的应用程序不一定会把自己的端口号写入该字段中。如果不写入端口号,则把这个字段设置为 0。这样,接收端的应用程序就不能发送响应了。
- 目的端口:接收端计算机上 udp 软件使用的端口,占据 16 位。
- 长度:该字段占据 16 位,表示 udp 数据报长度,包含 udp 报文头和 udp 数据长度。因为 udp 报文头长度是 8 个字节,所以这个值最小为 8。
- 校验值:该字段占据 16 位,可以检验数据在传输过程中是否被损坏。
三次握手是指建立tcp连接协议时,需要在客户端和服务器之间发送三个包,握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据
第一次握手:
客户端将tcp报文标志位syn置为1,随机产生一个序号值seq=j,保存在tcp首部的***(sequence number)字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务器端,发送完毕后,客户端进入syn_sent状态,等待服务器端确认。
第二次握手:
服务器端收到数据包后由标志位syn=1知道客户端请求建立连接,服务器端将tcp报文标志位syn和ack都置为1,ack=j 1,随机产生一个序号值seq=k,并将该数据包发送给客户端以确认连接请求,服务器端进入syn_rcvd状态。
第三次握手:
客户端收到确认后,检查ack是否为j 1,ack是否为1,如果正确则将标志位ack置为1,ack=k 1,并将该数据包发送给服务器端,服务器端检查ack是否为k 1,ack是否为1,如果正确则连接建立成功,客户端和服务器端进入established状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。
我们上面写的ack和ack,不是同一个概念:
- 小写的ack代表的是头部的确认号acknowledge number, 缩写ack,是对上一个包的序号进行确认的号,ack=seq 1。
- 大写的ack,则是我们上面说的tcp首部的标志位,用于标志的tcp包是否对上一个包进行了确认操作,如果确认了,则把ack标志位设置成1。
tcp为什么三次握手而不是两次握手?
- 为了实现可靠数据传输, tcp 协议的通信双方, 都必须维护一个***, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知***起始值, 并确认对方已经收到了***起始值的必经步骤
- 如果只是两次握手, 至多只有连接发起方的起始***能被确认, 另一方选择的***则得不到确认
《计算机网络》中是这样说的:
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
在书中同时举了一个例子,如下:
假如client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。
于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。
采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。
挥手请求可以是client端,也可以是server端发起的,我们假设是client端发起:
- 第一次挥手: client端发起挥手请求,向server端发送标志位是fin报文段,设置***seq,此时,client端进入fin_wait_1状态,这表示client端没有数据要发送给server端了。
- 第二次分手:server端收到了client端发送的fin报文段,向client端返回一个标志位是ack的报文段,ack设为seq加1,client端进入fin_wait_2状态,server端告诉client端,我确认并同意你的关闭请求。
- 第三次分手: server端向client端发送标志位是fin的报文段,请求关闭连接,同时client端进入last_ack状态。
- 第四次分手 : client端收到server端发送的fin报文段,向server端发送标志位是ack的报文段,然后client端进入time_wait状态。server端收到client端的ack报文段以后,就关闭连接。此时,client端等待2msl的时间后依然没有收到回复,则证明server端已正常关闭,那好,client端也可以关闭连接了。
为什么连接的时候是三次握手,关闭的时候却是四次握手?
建立连接时因为当server端收到client端的syn连接请求报文后,可以直接发送syn ack报文。其中ack报文是用来应答的,syn报文是用来同步的。所以建立连接只需要三次握手。
由于tcp协议是一种面向连接的、可靠的、基于字节流的运输层通信协议,tcp是全双工模式。
这就意味着,关闭连接时,当client端发出fin报文段时,只是表示client端告诉server端数据已经发送完毕了。当server端收到fin报文并返回ack报文段,表示它已经知道client端没有数据发送了,但是server端还是可以发送数据到client端的,所以server很可能并不会立即关闭socket,直到server端把数据也发送完毕。
当server端也发送了fin报文段时,这个时候就表示server端也没有数据要发送了,就会告诉client端,我也没有数据要发送了,之后彼此就会愉快的中断这次tcp连接。
为什么要等待2msl?
msl:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。
有以下两个原因:
- 第一点:保证tcp协议的全双工连接能够可靠关闭:
由于ip协议的不可靠性或者是其它网络原因,导致了server端没有收到client端的ack报文,那么server端就会在超时之后重新发送fin,如果此时client端的连接已经关闭处于cloesd状态,那么重发的fin就找不到对应的连接了,从而导致连接错乱,所以,client端发送完最后的ack不能直接进入closed状态,而要保持time_wait,当再次收到fin的收,能够保证对方收到ack,最后正确关闭连接。 - 第二点:保证这次连接的重复数据段从网络中消失
如果client端发送最后的ack直接进入closed状态,然后又再向server端发起一个新连接,这时不能保证新连接的与刚关闭的连接的端口号是不同的,也就是新连接和老连接的端口号可能一样了,那么就可能出现问题:如果前一次的连接某些数据滞留在网络中,这些延迟数据在建立新连接后到达client端,由于新老连接的端口号和ip都一样,tcp协议就认为延迟数据是属于新连接的,新连接就会接收到脏数据,这样就会导致数据包混乱。所以tcp连接需要在time_wait状态等待2倍msl,才能保证本次连接的所有数据在网络中消失。
rtt和rto
rtt:发送一个数据包到收到对应的ack,所花费的时间
rto:重传时间间隔(tcp在发送一个数据包后会启动一个重传定时器。rto即定时器的重传时间)
开始预先算一个定时器时间,如果回复ack,重传定时器就自动失效,即不需要重传;如果没有回复ack,rto定时器时间就到了,重传。rto是本次发送当前数据包所预估的超时时间,rto不是固定写死的配置,是经过rtt计算出来的。基于rto便有了重传机制。
滑动窗口
tcp使用滑动窗口做流量控制与乱序重排。
tcp的滑动窗口主要有两个作用:
1.保证tcp的可靠性
2.保证tcp的流控特性
tcp报文头有个字段叫window,用于接收方通知发送方自己还有多少缓存区可以接收数据,发送方根据接收方的处理能力来发送数据,不会导致接收方处理不过来,这便是流量控制。
发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口;同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口。发送窗口和接收窗口的序号的上下界不一定要一样,甚至大小也可以不同。不同的滑动窗口协议窗口大小一般不同。发送方窗口内的***代表了那些已经被发送,但是还没有被确认的帧,或者是那些可以被发送的帧
滑动窗口由四部分组成每个字节的数据都有唯一顺序的编码,随着时间发展,未确认部分与可以发送数据包编码部分向右移动,形式滑动窗口
- 绿色:发送成功并已经ack确认的数据
- 黄色:发送成功等待ack确认的数据(占用滑动窗口大小)
- 紫色:滑动窗口剩余大小可以发送的字节数量(滑动窗口可用大小)
- 灰色:后续数据编码
接收窗口的大小就是滑动窗口的最大值,数据传输过程中滑动窗口的可用大小是动态变化的。
但是还有这么一点,滑动窗口的设计仅仅是考虑到了处理方的处理能力,但是没有考虑到道路的通畅问题
就好像服务端可以处理100m数据,但是传输的数据99m都堵在路上了,这不就是导致道路阻塞了么?这就需要另外一个设计拥塞避免
流量控制的目的
如果发送者发送数据过快,接收者来不及接收,那么就会有分组丢失。
为了避免分组丢失,控制发送者的发送速度,使得接收者来得及接收,这就是流量控制。
流量控制根本目的是防止分组丢失,它是构成tcp可靠性的一方面。
如何实现流量控制
由滑动窗口协议(连续arq协议)实现。滑动窗口协议既保证了分组无差错、有序接收,也实现了流量控制。
主要的方式就是接收方返回的 ack 中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。
流量控制引发的死锁
当发送者收到了一个窗口为0的应答,发送者便停止发送,等待接收者的下一个应答。但是如果这个窗口不为0的应答在传输过程丢失,发送者一直等待下去,而接收者以为发送者已经收到该应答,等待接收新数据,这样双方就相互等待,从而产生死锁。
为了避免流量控制引发的死锁,tcp使用了持续计时器。每当发送者收到一个零窗口的应答后就启动该计时器。时间一到便主动发送报文询问接收者的窗口大小。若接收者仍然返回零窗口,则重置该计时器继续等待;若窗口不为0,则表示应答报文丢失了,此时重置发送窗口后开始发送,这样就避免了死锁的产生。
为什么要进行拥塞控制
假设网络已经出现拥塞,如果不处理拥塞,那么延时增加,出现更多丢包,触发发送方重传数据,加剧拥塞情况,继续恶性循环直至网络瘫痪。可知,拥塞控制与流量控制的适应场景和目的均不同。
拥塞发生前,可避免流量过快增长拖垮网络;拥塞发生时,唯一的选择就是降低流量。
主要使用4种算法完成拥塞控制:
- 慢启动
- 拥塞避免
- 快重传算法
- 快速恢复算法
算法1、2适用于拥塞发生前,算法3适用于拥塞发生时,算法4适用于拥塞解决后(相当于拥塞发生前)。
rwnd与cwnd
rwnd(receiver window,接收者窗口)与cwnd(congestion window,拥塞窗口):
- rwnd是用于流量控制的窗口大小,主要取决于接收方的处理速度,由接收方通知发送方被动调整。
- cwnd是用于拥塞处理的窗口大小,取决于网络状况,由发送方探查网络主动调整。
同时考虑流量控制与拥塞处理,则发送方窗口的大小不超过min{rwnd, cwnd}。
慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。
这里用报文段的个数作为拥塞窗口的大小举例说明慢开始算法,实际的拥塞窗口大小是以字节为单位的。
一个传输轮次所经历的时间其实就是往返时间rtt,而且每经过一个传输轮次,拥塞窗口cwnd就加倍。
为了防止cwnd增长过大引起网络拥塞,还需设置一个慢开始门限ssthresh状态变量。ssthresh的用法如下:
- cwnd
- 当cwnd>ssthresh时,改用拥塞避免算法。
- 当cwnd=ssthresh时,慢开始与拥塞避免算法任意
注意,这里的“慢”并不是指cwnd的增长速率慢,而是指在tcp开始发送报文段时先设置cwnd=1,然后逐渐增大,这当然比按照大的cwnd一下子把许多报文段突然注入到网络中要“慢得多”。
让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间rtt就把发送方的拥塞窗口cwnd加1,而不是加倍。这样拥塞窗口cwnd按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多
无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有按时收到确认,虽然没有收到确认可能是其他原因的分组丢失,但是因为无法判定,所以都当做拥塞来处理),就把慢开始门限ssthresh设置为出现拥塞时的发送窗口大小的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。
整个拥塞控制的流程如下图:
1.拥塞窗口cwnd初始化为1个报文段,慢开始门限初始值为16
2.执行慢开始算法,指数规律增长到第4轮,即cwnd=16=ssthresh,改为执行拥塞避免算法,拥塞窗口按线性规律增长
3.假定cwnd=24时,网络出现超时(拥塞),则更新后的ssthresh=12,cwnd重新设置为1,并执行慢开始算法。当cwnd=12=ssthresh时,改为执行拥塞避免算法
注意:“拥塞避免”并非完全能够避免了阻塞,而是使网络比较不容易出现拥塞。
快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方,可提高网络吞吐量约20%)而不要等到自己发送数据时捎带确认。
快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期
快重传配合使用的还有快恢复算法,有以下两个要点:
当发送方连续收到三个重复确认时,就把ssthresh门限减半(为了预防网络发生拥塞)。
但是接下去并不执行慢开始算法
考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将cwnd设置为ssthresh减半后的值,然后执行拥塞避免算法,使cwnd缓慢增大。
如下图:是目前使用最广泛的版本。
注意:在采用快恢复算法时,慢开始算法只是在tcp连接建立时和网络出现超时时才使用
在浏览器地址栏键入url,按下回车之后经历的流程
1.dns解析:浏览器会依据url逐层查询dns服务器缓存,解析url中的域名对应的ip地址,dns缓存从近到远依次是浏览器缓存、系统缓存、路由器缓存、ips服务器缓存、域名服务器缓存、顶级域名服务器缓存。
从哪个缓存找到对应的ip直接返回,不再查询后面的缓存。
2.tcp连接:结合三次握手
3.发送http请求:浏览器发出读取文件的http请求,该请求发送给服务器
4.服务器处理请求并返回http报文:服务器对浏览器请求做出响应,把对应的带有html文本的http响应报文发送给浏览器
5.浏览器解析渲染页面
6.连接结束:浏览器释放tcp连接,该步骤即四次挥手。
第5步和第6步可以认为是同时发生的,哪一步在前没有特别的要求
状态码由3位数字组成,第一位定义响应的类别
1xx:指示信息,表示请求以接收,继续处理
2xx:成功,表示请求已经被成功接收、理解、接受
- 200 ok:正常返回信息
3xx:重定向,要完成请求必须进行进一步操作
- 301:永久性转移,旧地址的资源已经被永久地移除了。搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址
- 302:暂时性转移,旧地址的资源还在,只是临时地从旧地址跳转到新地址,搜索引擎会抓取新的内容而保存旧的网址。
4xx:客户端错误,请求由语法错误或请求无法实现
- 400 bad request:客户端请求有语法错误,不能被服务器所理解。此时需要分析客户端的代码,去看看请求为什么出现服务 器无法理解的错误。
- 401 unauthorized:缺失或错误的认证,这个状态代码必须和www-authenticate报头域一起使用。
- 403 forbidden:客户端请求没有权限去访问要求的资源。
- 404 not found:请求资源不存在,检擦url或路径配置。
5xx:服务器错误,服务器未能实现合法的请求
- 500 internal server error:服务器发生不可预测的错误。检查服务器日志,看看里面的代码哪里错误,进而抛出异常。
- 502 bad gateway:服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答。
- 503 server unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常。
- 504 gateway timeout:网关超时,由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答。
get请求和post请求的区别
- get 请求的请求参数是添加到 head 中,可以在 url 中可以看到;post 请求的请求参数是添加到body中,在url 中不可见。
- 请求的url有长度限制,这个限制由浏览器和 web 服务器决定和设置的。例如ie浏览器对 url的最大限制为2083个字符,如果超过这个数字,提交按钮没有任何反应。因为get请求的参数是添加到url中,所以get请求的url的长度限制需要将请求参数长度也考虑进去。而post请求不用考虑请求参数的长度。
- get请求产生一个数据包; post请求产生2个数据包,在火狐浏览器中,产生一个数据包。这个区别点在于浏览器的请求机制,先发送请求头,再发送请求体。因为get没有请求体,所以就发送一个数据包,而post包含请求体,所以发送两次数据包,但是由于火狐机制不同,所以发送一个数据包。
- get 请求会被浏览器主动缓存下来,留下历史记录,而 post 默认不会。
- get是幂等的,而post不是。(幂等表示执行相同的操作,结果也是相同的)
长连接(persistentconnection)
http 1.1支持长连接(persistentconnection)
http 1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个tcp连接,服务器完成请求处理后立即断开tcp连接,服务器不跟踪每个客户也不记录过去的请求。
http 1.1则支持持久连接persistent connection, 并且默认使用,在同一个tcp的连接中可以传送多个http请求和响应. 多个请求和响应可以重叠,多个请求和响应可以同时进行. 更加多的请求头和响应头
http 1.1的持续连接,也需要增加新的请求头来帮助实现,例如,connection请求头的值为keep-alive时,客户端通知服务器返回本次请求结果后保持连接;connection请求头的值为close时,客户端通知服务器返回本次请求结果后关闭连接。
流水线(pipelining)
请求的流水线(pipelining)处理,在一个tcp连接上可以传送多个http请求和响应,减少了建立和关闭连接的消耗和延迟。
例如:一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接。 http 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容。
host字段
在http1.0中认为每台服务器都绑定一个唯一的ip地址,因此,请求消息中的url并没有传递主机名。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个ip地址。
http1.1的请求消息和响应消息都应支持host头域,且请求消息中如果没有host头域会报告一个错误(400 bad request)。此外,服务器应该接受以绝对路径标记的资源请求。
100(continue) status
http/1.1加入了一个新的状态码100(continue)。客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(unauthorized);如果服务器接收此请求就回送响应码100,客户端就可以继续发送带实体的完整请求了。100 (continue) 状态代码的使用,允许客户端在发request消息body之前先用request header试探一下server,看server要不要接收request body,再决定要不要发request body。
chunked transfer-coding
http/1.1将发送方将消息分割成若干个任意大小的数据块,每个数据块在发送时都会附上块的长度,最后用一个零长度的块作为消息结束的标志。这种方法允许发送方只缓冲消息的一个片段,避免缓冲整个消息带来的过载。
cache
http/1.1在1.0的基础上加入了一些cache的新特性,当缓存对象的age超过expire时变为stale对象,cache不需要直接抛弃stale对象,而是与源服务器进行重新**(revalidation)。
session的实现方式:
1.使用cookie来实现。服务器给每个session分配一个唯一的jsession id,并通过cookie发送给客户端。客户端发起新的请求的时候,将在cookie头中携带的jsession id,服务器找到客户端对应的session。
2.使用url回写来实现。url回写是指服务器在发送给浏览器页面的所有链接都携带jsession id的参数,客户端点击任何一个链接,都会把jsession id带回服务器,如果直接在浏览器输入服务端资源的url来请求该资源,session是匹配不到的。
tomcat对session的实现是一开始同时使用cookie和url回写机制,如果发现客户端支持cookie,就继续使用cookie,停止使用url回写;如果发现cookie被禁用,就一直使用url回写。
cookie与session的区别
- cookie的数据信息存放在客户端浏览器上,session的数据信息存放在服务器上。
- 单个cookie保存的数据<=4kb,一个站点最多保存20个cookie。对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。
- cookie中只能保管ascii字符串,并需要通过编码方式存储为unicode字符或者二进制数据。session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。
- cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,所以它是不安全的。session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。
- 开发可以通过设置cookie的属性,达到使cookie长期有效的效果。session依赖于名为jsessionid的cookie,而cookie jsessionid的过期时间默认为-1,只需关闭窗口该session就会失效,因而session不能达到长期有效的效果。
- cookie保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。
http与https的区别
http 是明文传输协议,https 协议是由 ssl http 协议构建的可进行加密传输、身份认证的网络协议,比 http 协议安全
- https比http更加安全,对搜索引擎更友好,利于seo,谷歌、百度优先索引https网页;
- https需要用到ssl证书,而http不用;
- https标准端口443,http标准端口80;
- https基于传输层,http基于应用层;
- https在浏览器显示绿色安全锁,http没有显示;
工作原理
https 协议会对传输的数据进行加密,而加密过程是使用了非对称加密实现。但其实,https 在内容传输的加密上使用的是对称加密,非对称加密只作用在证书验证阶段
https的整体过程分为证书验证和数据传输阶段,具体的交互过程如下:
1.client发起一个https(比如
https://juejin.im/user/4283353031252967)的请求
2.server把事先配置好的公钥证书返回给客户端。
3.client验证公钥证书:比如是否在有效期内,证书的用途是不是匹配client请求的站点,是不是在crl吊销列表里面,它的上一级证书是否有效,这是一个递归的过程,直到验证到根证书(操作系统内置的root证书或者client内置的root证书)。如果验证通过则继续,不通过则显示警告信息。
4.client使用伪随机数生成器生成加密所使用的对称**,然后用证书的公钥加密这个对称**,发给server。
5.server使用自己的私钥解密这个消息,得到对称**。至此,client和server双方都持有了相同的对称**。
6.server使用对称**加密“明文内容a”,发送给client。
7.client使用对称**解密响应的密文,得到“明文内容a”。
8.client再次发起https的请求,使用对称**加密请求的“明文内容b”,然后server使用对称**解密密文,得到“明文内容b”。