网路协议
OSI开放式互联网参考模型(七层协议)
自治-无主从顺序
计算机网络的功能:
- 数据通信
- 资源共享
- 分布式处理:多台计算机各自承担同一工作任务的不同部分
- 提高可靠性
- 负载均衡
- .....
计算机网络的组成:
计算机网络的分类
其中网状型是广域网常见的网络结构
标准化工作:
- 法定标准:OSI
- 事实标准: TCP/IP
速率-带宽等各种指标基础
-
速率相关的性能指标
速率即数据率或称数据传输率或比特率
比特 1/0 位, ==速率之间的换算是$10^3$==
-
“带宽“原本指的是某个信号具有的频带宽度。即最高频率与最低频率之差,单位是赫兹
计算机网络中,带宽用来表示网络的通信线路传输数据的能力,通常是指单位时间内从网络的某一点到另一点能通过的”最高数据率“。单位是”比特每秒“,b/s,kb/s,Mb/s,Gb/s。
带宽并不是指的单个bit的传输速率,而是指的是带宽允许每单位时间能同时进入多少个bit
-
吞吐量:表示在单位时间内通过某个网络(或信道、接口)的数据量。单位b/s,kb/s,Mb/s等。
-
时延
指数据(报文/分组/比特流)从网络(或链路)的一端传送到另一端所需的时间。也叫延迟或迟延。单位是s。
- 传输时延指的是把数据放到信道上的时延,这主要是跟信道带宽有关。
- 传播时延指的是数据从a到b的时延,主要跟信道长度有关
- 排队时延主要是等待路由器有空的时间
- 处理时延,路由器需要对数据进行一些校验的工作的时间
高速链路指的是信道带宽非常宽。在数据长度不变的情况下,发送时延非常小
-
时延带宽积
$时延带宽积=传播时延X带宽$ ,时延带宽积又称为以比特为单位的链路长度。即”某段链路现在有多少比特“。在不考虑发送时延的情况下,时延带宽积就是值”某段链路现在有多少比特“。 -
往返时延RTT:从发送放发送数据开始,到发送方收到接受方的确认(接收方收到数据后立即发送确认。总共经历的时延)
ping www.baidu.com 的时间就是往返时延。
(base) liuxin@liuxin:~$ ping www.baidu.com PING www.a.shifen.com (182.61.200.6) 56(84) bytes of data. 64 bytes from 182.61.200.6 (182.61.200.6): icmp_seq=1 ttl=48 time=30.1 ms 64 bytes from 182.61.200.6 (182.61.200.6): icmp_seq=2 ttl=48 time=30.1 ms
RTT包括:往返传播时延=传播时延*2 , 末端处理时间。
- 为什么要分层?
- 协议是对等实体数据交换而建立的规则、标准或约定,称为网络协议。
- 服务:下层为相邻上层提供的功能。
- 从上到下:逐层变长,PDU
-
概念总结由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。
## OSI参考模型
-
应用层:所有能和用户交互产生网络流量的程序(qq,邮箱)
典型应用服务(ftp),电子邮件(SMTP),万维网(HTTP)
-
表示层:用于处理在两个通信系统中交换信息的表示方式(语法和语义)
功能一:数据格式变换
功能二:数据加密解密
功能三: 数据压缩和恢复
-
会话层:向表示层实体/用户进程提供建立连接并在连接上有序地传输数据。这是会话,也是建立同步(SYN)
功能一:建立,管理,终止会话。比如两个不用的网页,就会建立会话,会话是独立的。
功能二:使用校验点可使会话在通信失效时从校验点/同步点继续恢复通信,实现数据同步。
-
传输层:**负责主机中两个进程的通信,即端到端的通信。传输单位是报文段或用户数据。**每个进程到占用一个端口号,所以是端到端的通信。
功能一:可靠传输、不可靠传输
功能二:差错控制
功能三:流量复用
功能四:复用分用(复用:多个应用程序可同时使用下面运输层的服务。分用:运输层把收到的信息分别交付给上面应用层中相应的进程)
比如说:两个进程用了两个端口,传输层会把这两个端口上的报文都分配到下面三层,下面三层都是复用的,然后传输到目标设备上后又根据ip号进行重新划分。
-
网络层(又叫做IP层):主要任务是把分组从源端传到目的端,为分组交换网上的不同主机提供通信服务。网络层传输单位是数据报。
分组:当数据报过长的时候,对数据报进行分组切割,然后把分组放到数据链路上去传递。
功能一:路由控制(选出最佳路径)
功能二:流量控制(对于发送端速度控制)
功能三:差错控制(进行差错检查,比如奇偶校验等)
功能四:拥塞控制(若所有结点都来不及接受分组,而要丢弃大量分组的话,网络就处于拥塞状态。因此要采取一定措施,缓解这种拥塞)。
-
数据链路层:主要任务是把网络层传下来的数据报组装成帧。数据链路层/链路层的传输单位是帧。
功能一:成帧(定义帧的开始和结束)
功能二:差错控制 (帧错+位错)
功能三:流量控制
功能四:访问(接入)控制 控制对信道的访问
-
物理层:主要任务是在物理媒体上实现比特流的透明传输
功能一:定义接口特性
功能二:定义传输模式 单工、半双工、双工。
功能三:定义传输速率
功能四:比特编码
**应用层:**向用户提供一组常用的应用程序,比如电子邮件、文件传输访问、远程登录等。远程登录TELNET使用TELNET协议提供在网络其它主机上注册的接口。TELNET会话提供了基于字符的虚拟终端。文件传输访问FTP使用FTP协议来提供网络内机器间的文件拷贝功能。
**传输层:**提供应用程序间的通信。其功能包括:一、格式化信息流;二、提供可靠传输。为实现后者,传输层协议规定接收端必须发回确认,并且假如分组丢失,必须重新发送。
**网络层 :**负责相邻计算机之间的通信。其功能包括三方面:
一、处理来自传输层的分组发送请求,收到请求后,将分组装入IP数据报,填充报头,选择去往信宿机的路径,然后将数据报发往适当的网络接口。
二、处理输入数据报:首先检查其合法性,然后进行寻径–假如该数据报已到达信宿机,则去掉报头,将剩下部分交给适当的传输协议;假如该数据报尚未到达信宿,则转发该数据报。
三、处理路径、流控、拥塞等问题。
**网络接口层:**这是TCP/IP软件的最低层,负责接收IP数据报并通过网络发送之,或者从网络上接收物理帧,抽出IP数据报,交给IP层。
-
相关面试题
-
TCPServer
package com.interview.network.socket; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class TCPServer {xieyi public static void main(String[] args) throws Exception{ //创建socket,使得socket绑定到6500端口 ServerSocket ss = new ServerSocket(65000); while(true){TCP协议的三次握手 Socket socket = ss.accept(); new LengthCaculator(socket).start(); } } } class LengthCaculator extends Thread{ private Socket socket; public LengthCaculator(Socket socket) { this.socket = socket; } @Override public void run() { try { //获取socket的输出流 OutputStream os = socket.getOutputStream(); //获取socket的输入流 InputStream is = socket.getInputStream(); int ch = 0; byte[] buff = new byte[1024]; //buff 主要用来读取输入的内容,存成byte数组,ch主要用来获取读取数组的 ch=is.read(buff); //将字节流的byte数组转换成字符串,这里获取的内容是客户端 String content = new String(buff,0,ch); System.out.println(content); //往输出流里写入获得的字符串的长度,会发给客户端 os.write(String.valueOf(content.length()).getBytes()); is.close(); os.close(); } catch (IOException e) { e.printStackTrace(); } } }
TCPClient
xieyipackage com.interview.network.socket; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class TCPClient { public static void main(String[] args) throws Exception{ Socket socket = new Socket("127.0.0.1",65000); OutputStream os = socket.getOutputStream(); InputStream is = socket.getInputStream(); //只能写入Byte数组 os.write(new String("hello world").getBytes()); // int ch=0; byte[] buff = new byte[1024]; //从流中读入 ch=is.read(buff); // String content = new String(buff,0,ch); System.out.println(content); is.close(); os.close(); socket.close(); } }
UDPServer
package com.interview.network.socket; import java.net.DatagramPacket; import java.net.DatagramSocket; public class UDPServer { /** * * @param args * @throws Exception */ public static void main(String[] args) throws Exception{ DatagramSocket socket = new DatagramSocket(65001); byte[] buff = new byte[100]; //接受客户端发送过来的内容,并将内容封装进DatagramPacket DatagramPacket packet = new DatagramPacket(buff,buff.length); //接受客户端发过来的请求,这里应该是阻塞的 socket.receive(packet); byte[] data = packet.getData(); String content = new String(data,0,packet.getLength()); System.out.println(content); //将要发送给客户端的数据转成二进制 byte[] sendedContent =String.valueOf(content.length()).getBytes(); //服务端给客户短发送数据报 //从DatagramPacket对象中获取到数据的来源地址与端口号 DatagramPacket packetToClient =new DatagramPacket(sendedContent,sendedContent.length, packet.getAddress(),packet.getPort()); socket.send(packetToClient); //可以看出来这是一个无主从无连接的服务器,接收到一个数据包之后,就没有任何关系了, // 进行回复就是往对面地址发一个数据包 } }
UDPClient
package com.interview.network.socket; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class TCPClient { public static void main(String[] args) throws Exception{ Socket socket = new Socket("127.0.0.1",65000); OutputStream os = socket.getOutputStream(); InputStream is = socket.getInputStream(); //只能写入Byte数组 os.write(new String("hello world").getBytes()); // int ch=0; byte[] buff = new byte[1024]; //从流中读入 ch=is.read(buff); // String content = new String(buff,0,ch); System.out.println(content); is.close(); os.close(); socket.close(); } }
IP 用于计算机之间的通信。
IP 是无连接的通信协议。它不会占用两个正在通信的计算机之间的通信线路。这样,IP 就降低了对网络线路的需求。每条线可以同时满足许多不同的计算机之间的通信需要。
通过 IP,消息(或者其他数据)被分割为小的独立的包,并通过因特网在计算机之间传送。
IP 负责将每个包路由至它的目的地。
每个计算机必须有一个 IP 地址才能够连入因特网。
每个 IP 包必须有一个地址才能够发送到另一台计算机。
网络上每一个节点都必须有一个独立的Internet地址(也叫做IP地址)。现在,通常使用的IP地址是一个32bit的数字,也就是我们常说的IPv4标准,这32bit的数字分成四组,也就是常见的255.255.255.255的样式。IPv4标准上,地址被分为五类,我们常用的是B类地址。具体的分类请参考其他文档。需要注意的是IP地址是网络号+主机号的组合,这非常重要。
CP/IP 使用 32 个比特来编址。一个计算机字节是 8 比特。所以 TCP/IP 使用了 4 个字节。
bash一个计算机字节可以包含 256 个不同的值:00000000、00000001、00000010、00000011、00000100、00000101、00000110、00000111、00001000 … 直到 11111111。
TCP 用于应用程序之间的通信。
当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信。这个全双工的通信将占用两个计算机之间的通信线路,直到它被一方或双方关闭为止。UDP 和 TCP 很相似,但是更简单,同时可靠性低于 TCP。
当一个 IP 包从一台计算机被发送,它会到达一个 IP 路由器。
IP 路由器负责将这个包路由至它的目的地,直接地或者通过其他的路由器。
在一个相同的通信中,一个包所经由的路径可能会和其他的包不同。而路由器负责根据通信量、网络中的错误或者其他参数来进行正确地寻址。
传输控制协议TCP简介
TCP/IP不是一个协议,而是一个协议族的统称。里面包括了IP协议,IMCP协议,TCP协议,以及我们更加熟悉的http、ftp、pop3协议等等。
- 面对连接的、可靠的、基于字节流的传输层通信协议
- 将应用层的数据流分割成报文段并发送给目标节点的TCP层(报文段的长度取决于该计算机网络传输的数据链路层的最大传输单元MTU)。
- 数据包都有序号,对方收到则发送ACK确认,未收到则重传
- TCP使用奇偶校验和来检验数据在传输过程中是否有误
基本概念
-
端口号:无论是TCP还是UDP都是有源端口和目的端口这个概念的,但是在发送或者接收的数据包中是不包含数据端口的。所以端口号这些东西是属于传输层的只是范畴的。由于计算机的进程号在只在本地唯一,所以利用端口号去标记唯一进程。
利用IP地址+协议+端口号去标识网络中进程,这种唯一标识进程的方式叫做套接字。
-
序号(sq):占了4个字节,TCP连接中传送的字节流的每一个字节都按顺序去编号,例如一段报文的序号字段值是107,而携带的数据共有100个字节,下一个报文段是就是100+107=207开始
-
确认号(ack) ,4个字节,是期望收到下一个报文的第一个数据字节的序号
-
4位首部长度:4位包括TCP头大小,指示何处数据开始。
-
保留(6位):6位值域,这些位必须是0。为了将来定义新的用途而保留。
-
标志:6位标志域。表示为:紧急标志、有意义的应答标志、推、重置连接标志、同步序列号标志、完成发送数据标志。按照顺序排列是:URG、ACK、PSH、RST、SYN、FIN。
URG:紧急标志。紧急标志为"1"表明该位有效。
ACK:确认标志。表明确认编号栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据。
PSH:推标志。该标志置位时,接收端不将该数据进行队列处理,而是尽可能快地将数据转由应用处理。在处理Telnet或rlogin等交互模式的连接时,该标志总是置位的。
RST:复位标志。用于复位相应的TCP连接。
SYN:同步标志。表明同步序列编号栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列编号看作是一个范围从0到4,294,967,295的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号。
FIN:结束标志。
-
16位窗口大小:用来表示想收到的每个TCP数据段的大小。TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个16字节字段,因而窗口大小最大为65535字节。
-
16位校验和:16位TCP头。源机器基于数据内容计算一个数值,收信息机要与源机器数值 结果完全一样,从而证明数据的有效性。检验和覆盖了整个的TCP报文段:这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证的
-
16位紧急指针:指向后面是优先数据的字节,在URG标志设置了时才有效。如果URG标志没有被设置,紧急域作为填充。加快处理标示为紧急的数据段。
(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
简单来说,就是
1、建立连接时,客户端发送SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认
2、服务器收到SYN包,必须确认客户的SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态
3、客户端收到服务器的SYN+ACK包,向服务器发送确认报ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,客户端与服务器开始传送数据。
主要是为了初始化两边seq的初始值,不然后续的解析会有问题。
### 首次握手的隐患---SYN超时
问题起因分析:
- server收到Client的SYN,回复SYN-ACK的时候未收到ACK确认(有可能就掉线了)
- Server不断重试直至超时,linux默认等待63秒才断开连接(一般会重试5次,时间间隔为:1s,2s,4s,8s,16s)最后一次需要等待32s,总共63秒。
SYN Flood攻击
针对此特点,服务器可能遭到SYN Flood攻击
在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:
#netstat -nap | grep SYN_RECV
针对SYN Flood的防护措施
- SYN队列满后,通过tcp_syncookies参数回发SYN Cookie
- 若为正常连接则Client会回发SYN Cookie,直接建立连接。
具体原理:
-
server在收到sync包后,判断是否需要使用sync cookie,如果需要使用,则server根据流的源/宿ip、源/宿端口、序列号以及mss值hash成一个cookie,然后作为sync+ack报文的初始序列号发送给client,server本地不保存相关的request_sock信息;
-
client收到sync+ack后,将序列号加1,然后返回ack给server;
-
server收到ack后,先从半连接队列里找request_sock,如果找不到,则进行sync cookie判断,判断方法是:
将包的ack_seq序列号减1,减完1后的序列号值即为server一开始初始化创建的cookie值;
根据收到的ack包的源/宿ip、源/宿端口、及序列号减1重新hash一个cookie值,然后跟上一步得到的cookie比较,并得到mss值,则正常创建request_sock,然后更新相关信息,将sk->sk_state置为ESTABLISHED状态,request_sock保存到连接队列里。
建立连接后,Client出现故障怎么办
保活机制
- 向对方发送保活探测报文,如果未收到响应则继续发送
- 尝试次数达到保活探测数仍未收到响应则中断连接
所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发,整个流程如下图所示:
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。 由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
==这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。==
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
原因有二:
一、保证TCP协议的全双工连接能够可靠关闭
二、保证这次连接的重复数据段从网络中消失
先说第一点,如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。
再说第二点,如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。
UDP的特点
- 面向非连接
- 不维护连接状态,支持同时向多个客户端传输相同的消息
- 数据包报头只有8个字节,额外开销较小
- 吞吐量只受限于数据生成速率、传输速率以及机器性能
- 尽最大努力交付,不保证可靠交付,不需要维持复杂的链接状态表
- 面向报文,不对应用程序提交的报文信息进行拆分或者合并
- 面向连接 VS 无连接
- 可靠性
- 有序性
- 速度
- 量级(TCP重量级,UDP轻量级,体现在包头)
## TCP的滑动窗口
TCP使用滑动窗口做流量控制与乱序重排:
- 保证TCP的可靠性
RTT和RTO:
- RTT:发送一个数据包收到对应的ACK,所花费的时间
- RTO:重传时间间隔(RTO不是一个固定的设置,是由RTT计算出来的。)
窗口数据的计算过程
TCP的发送端和接收端都维护一个窗口
对于接收端(从左到右):
LastByteRead是指已经接收并且已经回复的连续最大seq的位置
LastByteExpected是指已经收到但还没有发送ACK的最大seq的位置
LastByteRcvd是指已经收到的最后一个字节的sq的位置
LastByteExpected与LastByteRcvd中间有一段空白的区域,是指小于LastByteRcvd但是又还没收到的报文(可能是丢失了)。
对于发送端(从左到右):
LastByteAcked是指发送端已经应答的报文的最后位置
LastByteSent是指发送端已经发送的报文的最后的位置
LasByteWrittern是指发送端已经写入的报文的最后的位置
滑动过程示意图:
图中32到51就是当前滑动窗口的范围,当34 35收到应答但是32 33收到应答的时候,窗口不会移动,一定要32收到应答窗口才会移动。
由于ack是有TCP栈进行自动回复的,所以不存在时延,因此已接收但是为回复ack的情况是不存在的。所以未接收但是准备接收的长度就是接收窗口。
-
超文本传输协议HTTP主要特点:
- 支持客户/服务器模式
- 简单快速
- 灵活(运输传输任意类型的数据对象)
- 无连接(限制TCP的每次连接都处理一个请求,收到后直接断开请求)
- 无状态(没有记忆,不能处理之前的信息)
1.1用得最为广泛,相对于1.0,最大的区别是引入了keep-alive长连接技术
-
HTTP请求结构
http请求报文包括:请求行;请求头部;请求空行;请求正文。
下图是一个请求报文:
- DNS解析
- TCP连接
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
- 连接结束
五种可能的取值:
1xx:指示信息--表示请求已接收,继续处理
2xx:成功--表示请求一杯成功接收、理解、接受
3xx:重定向--要完成请求必须进行进一步的操作(往往是跟跳转相关的)
4xx:客户端错误--请求有语法错误或者请求无法实现
各类别常见状态码:
-
2xx (3种)
**200 OK:**表示从客户端发送给服务器的请求被正常处理并返回;
**204 No Content:**表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
**206 Patial 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报文层面:GET将请求信息放在URL(URL长度是有限制的),POST放在报文体中。
-
数据库层面:GET符合幂等性和安全性,POST不符合。
幂等性:对数据库的一次操作或多次操作获得的结果是一致的。
安全性:对数据库的操作没有改变数据库原有的数据
-
其他层面:GET可以被缓存、被存储,而POST不行。
Cookie简介
-
是由服务器发给客户端的特殊信息,以文本的形式存放在客户端
具体而言,在访问支持Cookie的网站的时候,用户会提供账户名,密码等信息并提交至服务器,紧接着服务器在向客户端回传相应的超文本的同时也会发回这些个人信息,当然这些信息并不存放在http响应体,而是存放在http响应头,当用户端浏览器接受到来自服务器的相应之后,浏览器会将这些信息存放在一个统一的位置。
-
客户端再次请求时,会把Cookie回发,这次个人信息就会存在http请求头里面了。
-
服务器收到后,会解析Cookie生成与客户端相对应的内容
Session简介
- 服务器端的机制,在服务器上保存的信息
- 解析客户端请求并操作Session id,按需保存状态信息
Session的实现方式
-
使用Cookie来实现:
服务器在解析的时候回去查找Session id字段,如果没找到就会分配一个J Session id给客户端,并通过Cookie发送给客户端,当客户端发起新的请求的时候,将在Cookie头中携带J Seesion id。
-
使用URL回写来实现
Cookie和Seesion的区别
- Cookie数据存放在客户的浏览器上,Seesion数据放在服务器上
- Session相对于Cookie更安全
- 但Seesion会占用服务器的内存,要减轻服务器的开销,应当使用Cookie
- 为网络通信提供安全及数据完整性的一种安全协议
- 是操作系统对外的API,SSL3.0后更名为TLS
- 采用身份验证和数据加密保证网络通信的安全和数据的完整性
- 对称加密:加密和解密都使用同一个秘钥
- 非对称加密:加密使用的秘钥和解密使用的秘钥是不相同的
- 哈希算法:将任意长度的信息转换为固定长度的值,算法不可逆(常见的是MD5算法)
- 数字签名:证明某个消息或者文件是某人发出/认同的(签名就是在信息的后面加上一段内容,这些内容是经过哈希后的值,可以证明信息没有被修改过)
- 浏览器将支持的加密算法信息发送给服务器
- 服务器选择一套浏览器支持的加密算法,以证书的形式回发浏览器
- 浏览器验证证书合法性,并结合证书公钥加密信息发送给服务器
- 服务器使用私钥解密信息,验证哈希,加密响应消息回发浏览器
- 浏览器解密响应消息,并对消息进行验证,之后进行加密交互数据