计算机网络

目录

计算机网络... 1

1, select, poll, epoll ?. 1

2, TCP三次握手?... 3

3,四次挥手?... 4

4, TCP和UDP区别... 6

5,TCP拥塞控制?... 7

SYN-Flood攻击... 8

http和https区别... 10

对称加密,非对称加密... 11

HTTP/1.X 和 HTTP/2.0 的区别... 12

什么是TCP粘包问题?... 13

Cookie和session. 14

HTTP Header 15

GET 和 POST 的区别... 16

计算机网络

 

1, select, poll, epoll ?

select,poll,epoll都是IO多路复用的机制。I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。

(而redis就是使用的epoll模式的IO模型)

fd:文件描述符

文件描述符(file descriptor)是内核为了高效管理这些已经被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符来实现。

select

select基于fd_set结构体(一个long类型数组),数组内的每一个元素都与一个fd相关联。select是基于遍历来查找fd事件的,所以时间复杂度为O(n)。

select 为什么是1024?两个1024

1,select中存放文件描述符的数组大小FD_SETSIZE为1024

2,进程的文件描述符上限默认是1024,正是因为这个原因,select设计时才把数组大小设计为1024

(进程的文件描述符上限是可以手动修改的,但是select的数组大小改不了,要改只能重新编译内核)

int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

select函数执行流程

  • 从用户空间拷贝fd_set(注册的事件集合)到内核空间
  • 遍历所有fd文件,并将当前进程挂到每个fd的等待队列中,当某个fd文件设备收到消息后,会唤醒设备等待队列上睡眠的进程,那么当前进程就会被唤醒
  • 如果遍历完所有的fd没有I/O事件,则当前进程进入睡眠,当有某个fd文件有I/O事件或当前进程睡眠超时后,当前进程重新唤醒再次遍历所有fd文件

缺点

1、每次调用select, 都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

2、同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时很大

3、select支持的文件描述符数量太小了,默认是1024。

优点:

1、select的可移植性更好,在某些Unix系统上不支持poll()。

2、select对于超时值提供了更好的精度:微秒,而poll是毫秒。

Poll

int poll (struct pollfd *fds, unsigned int nfds, int timeout);

不同与select使用三个位图来表示三个fdset的方式,poll使用一个 pollfd的指针实现

优点:

1、poll() 不要求开发者计算最大文件描述符加一的大小。

2、poll() 在应付大数目的文件描述符的时候速度更快,相比于select。

3、它没有最大连接数的限制,原因是它是基于链表来存储的。

Epoll

epoll是poll和select的改进版,能够显著的提高在大量并发连接中只有少数连接活跃的系统CPU利用率。epoll里面有三个函数,分别是:epoll_create(用于创建一个epoll句柄), epoll_wait(用于等待一个事件), epoll_ctl(用于注册要监听的事件类型).

1、对于第一个缺点,epoll的解决方案在epoll_ctl函数中。每次注册新的事件到epoll句柄中时(在epoll_ctl中指定EPOLL_CTL_ADD),会把所有的fd拷贝进内核,而不是在epoll_wait的时候重复拷贝。epoll保证了每个fd在整个过程中只会拷贝一次

2、对于第二个缺点,epoll的解决方案不像select或poll一样每次都把current轮流加入fd对应的设备等待队列中,而只在epoll_ctl时把current挂一遍(这一遍必不可少)并为每个fd指定一个回调函数,当设备就绪,唤醒等待队列上的等待者时,就会调用这个回调函数,而这个回调函数会把就绪的fd加入一个就绪链表)。epoll_wait的工作实际上就是在这个就绪链表中查看有没有就绪的fd(利用schedule_timeout()实现睡一会,判断一会的效果,和select实现中的第7步是类似的)。

3、对于第三个缺点,epoll没有这个限制,它所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。

epoll的优点:

1、没有最大并发连接的限制,能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口);
2、效率提升,不是轮询的方式,不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数;
即Epoll最大的优点就在于它只管你“活跃”的连接,而跟连接总数无关,因此在实际的网络环境中,Epoll的效率就会远远高于select和poll。

3、 内存拷贝,select和poll在数据准备好之后,需要把数据从内核拷贝到用户进程,epoll使用了“共享内存”,避免了内存拷贝。

epoll存在的问题:

当活跃连接数过多时可能会有性能问题。

epoll机制需要很多回调函数,在连接数较少的情况下,性能可能不如select和poll。

epoll对文件描述符的操作有两种模式LT(level trigger)ET(edge trigger)。LT模式是默认模式,LT模式与ET模式的区别如下:
  LT模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。
  ET模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。ET模式在很大程度上减少了epoll事件被重复触发的次数,因此效率要比LT模式高。

2, TCP三次握手?

 

三次握手是 TCP 连接的建立过程。在握手之前,主动打开连接的客户端结束 CLOSE 阶段,被动打开的服务器也结束 CLOSE 阶段,并进入 LISTEN 阶段。随后进入三次握手阶段:

① 首先客户端向服务器发送一个 SYN 包,并等待服务器确认,其中:

标志位为 SYN,表示请求建立连接;

序号为 Seq = x(x 一般取随机数);

随后客户端进入 SYN-SENT 阶段。

② 服务器接收到客户端发来的 SYN 包后,对该包进行确认后结束 LISTEN 阶段,并返回一段 TCP 报文,其中:

标志位为 SYN 和 ACK,表示确认客户端的报文 Seq 序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接;

序号为 Seq = y;

确认号为 Ack = x + 1,表示收到客户端的序号 Seq 并将其值加 1 作为自己确认号 Ack 的值,随后服务器端进入 SYN-RECV 阶段。

③ 客户端接收到发送的 SYN + ACK 包后,明确了从客户端到服务器的数据传输是正常的,从而结束 SYN-SENT 阶段。并返回最后一段报文。其中:

标志位为 ACK,表示确认收到服务器端同意连接的信号;

序号为 Seq = x + 1,表示收到服务器端的确认号 Ack,并将其值作为自己的序号值;

确认号为 Ack= y + 1,表示收到服务器端序号 seq,并将其值加 1 作为自己的确认号 Ack 的值。

随后客户端进入 ESTABLISHED。

当服务器端收到来自客户端确认收到服务器数据的报文后,得知从服务器到客户端的数据传输是正常的,从而结束 SYN-RECV 阶段,进入 ESTABLISHED 阶段,从而完成三次握手。

第二次为什么SYN和ACK合并一次发送?

SYN 被用于建立连接过程,在连接请求中,SYN=1和ACK=0 表示该段没有使用捎带确认字段.但是,连接应答捎带了一个确认,因此SYN=1和ACK=1.

本质上,SYN为被用来同时表示connection request 和connection accepted ,然后进一步用ACK来区分这两种可能.

3,四次挥手?

 

四次挥手即 TCP 连接的释放,这里假设客户端主动释放连接。在挥手之前主动释放连接的客户端结束 ESTABLISHED 阶段,随后开始四次挥手:

① 首先客户端向服务器发送一段 TCP 报文表明其想要释放 TCP 连接,其中:

标记位为 FIN,表示请求释放连接;

序号为 Seq = u;

随后客户端进入 FIN-WAIT-1 阶段,即半关闭阶段,并且停止向服务端发送通信数据。

② 服务器接收到客户端请求断开连接的 FIN 报文后,结束 ESTABLISHED 阶段,进入 CLOSE-WAIT 阶段并返回一段 TCP 报文,其中:

标记位为 ACK,表示接收到客户端释放连接的请求;

序号为 Seq = v;

确认号为 Ack = u + 1,表示是在收到客户端报文的基础上,将其序号值加 1 作为本段报文确认号 Ack 的值;

随后服务器开始准备释放服务器端到客户端方向上的连接。

客户端收到服务器发送过来的 TCP 报文后,确认服务器已经收到了客户端连接释放的请求,随后客户端结束 FIN-WAIT-1 阶段,进入 FIN-WAIT-2 阶段。

③ 服务器端在发出 ACK 确认报文后,服务器端会将遗留的待传数据传送给客户端,待传输完成后即经过 CLOSE-WAIT 阶段,便做好了释放服务器端到客户端的连接准备,再次向客户端发出一段 TCP 报文,其中:

标记位为 FIN 和 ACK,表示已经准备好释放连接了;

序号为 Seq = w;

确认号 Ack = u + 1,表示是在收到客户端报文的基础上,将其序号 Seq 的值加 1 作为本段报文确认号 Ack 的值。

随后服务器端结束 CLOSE-WAIT 阶段,进入 LAST-ACK 阶段。并且停止向客户端发送数据。

④ 客户端收到从服务器发来的 TCP 报文,确认了服务器已经做好释放连接的准备,于是结束 FIN-WAIT-2 阶段,进入 TIME-WAIT 阶段,并向服务器发送一段报文,其中:

标记位为 ACK,表示接收到服务器准备好释放连接的信号;

序号为 Seq= u + 1,表示是在已收到服务器报文的基础上,将其确认号 Ack 值作为本段序号的值;

确认号为 Ack= w + 1,表示是在收到了服务器报文的基础上,将其序号 Seq 的值作为本段报文确认号的值。

为什么三次握手?

三次握手的主要目的是确认自己和对方的发送和接收都是正常的,从而保证了双方能够进行可靠通信。若采用两次握手,当第二次握手后就建立连接的话,此时客户端知道服务器能够正常接收到自己发送的数据,而服务器并不知道客户端是否能够收到自己发送的数据。

现假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络节点长时间滞留了,以致延误到连接释放以后的某个时间才到B。本来这是一个已失效的报文段。但是B收到此失效的连接请求报文段后,就误认为是A有发出一次新的连接请求。于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了。

由于现在A并没有发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据。但B却以为新的运输连接已经建立了,并一直等待A发来数据。B的许多资源就这样白白浪费了。

采用三次握手的办法可以防止上述现象的发生。例如在刚才的情况下,A不会向B的确认发出确认。B由于收不到确认,就知道A并没有要求建立连接。

为什么四次挥手?

客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。

当主动方在数据传送结束后发出连接释放的通知,由于被动方可能还有必要的数据要处理,所以会先返回 ACK 确认收到报文。当被动方也没有数据再发送的时候,则发出连接释放通知,对方确认后才完全关闭TCP连接。

CLOSE-WAIT 和 TIME-WAIT

Close-wait

在服务器收到客户端关闭连接的请求并告诉客户端自己已经成功收到了该请求之后,服务器进入了 CLOSE-WAIT 状态,然而此时有可能服务端还有一些数据没有传输完成,因此不能立即关闭连接,而 CLOSE-WAIT 状态就是为了保证服务器在关闭连接之前将待发送的数据发送完成。

Time-wait

MSL是Maximum Segment Lifetime英文的缩写,中文可以译为 “报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。2MSL = 2*2mins = 4mins

客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:

  • 确保最后一个确认报文段能够到达。如果 B 没收到 A 发送来的确认报文段,那么就会重新发送连接释放请求报文段,A 等待一段时间就是为了处理这种情况的发生。
  • 等待一段时间是为了让本连接持续时间内所产生的所有报文段都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文段。

除此之外,假设客户端最后一次发送的 ACK 包在传输的时候丢失了,由于 TCP 协议的超时重传机制,服务端将重发 FIN 报文,若客户端并没有维持 TIME-WAIT 状态而直接关闭的话,当收到服务端重新发送的 FIN 包时,客户端就会用 RST 包来响应服务端,这将会使得对方认为是有错误发生,然而其实只是正常的关闭连接过程,并没有出现异常情况

4, TCP和UDP区别

  1. 是否面向连接 :UDP 在传送数据之前不需要先建立连接。而 TCP 提供面向连接的服务,在传送数据之前必须先建立连接,数据传送结束后要释放连接。
  2. 是否是可靠传输:远地主机在收到 UDP 报文后,不需要给出任何确认,并且不保证数据不丢失,不保证是否顺序到达。TCP 提供可靠的传输服务,TCP 在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制。通过 TCP 连接传输的数据,无差错、不丢失、不重复、并且按序到达。
  3. 是否有状态 :这个和上面的“是否可靠传输”相对应。TCP 传输是有状态的,这个有状态说的是 TCP 会去记录自己发送消息的状态比如消息是否发送了、是否被接收了等等。为此 ,TCP 需要维持复杂的连接状态表。而 UDP 是无状态服务,简单来说就是不管发出去之后的事情了(这很渣男!)。
  4. 传输效率 :由于使用 TCP 进行传输的时候多了连接、确认、重传等机制,所以 TCP 的传输效率要比 UDP 低很多。
  5. 传输形式 : TCP 是面向字节流的,UDP 是面向报文的。
  6. 首部开销 :TCP 首部开销(20 ~ 60 字节)比 UDP 首部开销(8 字节)要大。
  7. 是否提供广播或多播服务 :TCP 只支持点对点通信,UDP 支持一对一、一对多、多对一、多对多;

UDP 一般用于即时通信,比如: 语音、 视频 、直播等等。这些场景对传输数据的准确性要求不是特别高,比如你看视频即使少个一两帧,实际给人的感觉区别也不大。

TCP 用于对传输准确性要求特别高的场景,比如文件传输、发送和接收邮件、远程登录等等。

5,TCP拥塞控制?

慢开始、拥塞避免、快重传、快恢复。

发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量,注意拥塞窗口与发送方窗口的区别:拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口。

慢开始与拥塞避免

每次收到一个 ACK 报文将拥塞窗口(cwnd)加上一个 MSS(最大报文段),从 1 开始成指数级增长,具体来说,当新建连接时,cwnd初始化为1个最大报文段(MSS)大小,发送端开始按照拥塞窗口大小发送数据,每当有一个报文段被确认,cwnd就增加1个MSS大小。

拥塞避免:当 cwnd ≥ 慢启动阈值(sstresh)时,窗口按线性增长,每个轮次只将 cwnd 加 1。

(2)快重传与快恢复

  在接收方,要求每次接收到报文段都应该对最后一个已收到的有序报文段进行确认。例如已经接收到 M1 和 M2,此时收到 M4,应当发送对 M2 的确认。

  在发送方,如果收到三个重复确认,那么可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。例如收到三个 M2,则 M3 丢失,立即重传 M3。

  在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd/2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。慢开始和快恢复的快慢指的是 cwnd 的设定值,而不是 cwnd 的增长速率。慢开始 cwnd 设定为 1,而快恢复 cwnd 设定为 ssthresh。

 

流量控制

所谓流量控制就是让发送方的发送速率不要太快,让接收方来得及接收。如果接收方来不及接收发送方发送的数据,那么就会有分组丢失。在 TCP 中利用可变长的滑动窗口机制可以很方便的在 TCP 连接上实现对发送方的流量控制。主要的方式是接收方返回的 ACK 中会包含自己的接收窗口大小,以控制发送方此次发送的数据量大小(发送窗口大小)。

拥塞控制

在实际的网络通信系统中,除了发送方和接收方外,还有路由器,交换机等复杂的网络传输线路,此时就需要拥塞控制。拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的情况。常用的解决方法有:慢开始和拥塞避免、快重传和快恢复。

拥塞控制和流量控制的区别

拥塞控制往往是一种全局的,防止过多的数据注入到网络之中,而TCP连接的端点只要不能收到对方的确认信息,猜想在网络中发生了拥塞,但并不知道发生在何处,因此,流量控制往往指点对点通信量的控制,是端到端的问题。

流量控制是避免发送方的数据填满接收方的缓存,但并不知道网络中发生了什么。

计算机网络是处在一个共享的环境中。因此也有可能会发生网络的拥堵。在网络出现拥堵时,如果继续发送大量的数据包,可能会导致数据包时延、丢失,这时 TCP 就会重传数据,但是⼀重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包。

控制的目的就是避免发送方的数据填满整个网络。为了在发送方调节所要发送数据的数据量,定义了⼀个叫做「拥塞窗口」的概念。拥塞窗口 cwnd 是发送方维护的⼀个的状态变量,它会根据网络的拥塞程度动态变化的。

SYN-Flood攻击

SynFlood攻击方法有三种:

  1. 直接攻击:通过直接发送大量伪造TCP的方式进行攻击。在这种攻击中,由于攻击者不对IP地址进行隐蔽,导致攻击源单一,因此很容易发现并清理攻击者。
  2. IP欺骗攻击:通过IP地址的伪造,增加防御者的溯源难度。IP地址伪造技术的实现形式并不复杂 。首先创建一个具有IP报文格式的结构, 然后在该结构中源地址一项上填写虚假的IP地址, 最后将该报文写入输出设备发向目标主机。
  3. 分布式攻击(DDoS):如果攻击者控制大量肉鸡,使用僵尸网络发起攻击,那么攻击的溯源几乎无法进行。甚至有的攻击者还会命令每台设备进行IP地址的伪造,将两种攻击方式进行结合,对被攻击者造成难以抵御的伤害

客户端发送一个 SYN包 给服务端后就退出,而服务端接收到 SYN包 后,会回复一个 SYN+ACK包 给客户端,然后等待客户端回复一个 ACK包

但此时客户端并不会回复 ACK包,所以服务端只能一直等待直到超时。服务端超时后,会重发 SYN+ACK包 给客户端,默认会重试 5 次,而且每次等待的时间都会增加(可以参考 TCP 协议超时重传的实现)。

另外,当服务端接收到 SYN包 后,会建立一个半连接状态的 Socket。所以,当客户端一直发送 SYN包,但不回复 ACK包,那么将会耗尽服务端的资源,这就是 SYN Flood 攻击

防范:

增加积压队列(增加最大半连接数

目标设备上的每个操作系统都具有一定数量的半开放连接。对大量SYN数据包的一个响应是增加OS允许的可能半开连接的最大数量。为了成功增加最大积压,系统必须预留额外的内存资源来处理所有新的请求。如果系统没有足够的内存来处理增加的积压队列大小,系统性能将受到负面影响,但仍然可能优于拒绝服务。

回收最早的半开TCP连接

一旦积压已被填补,另一个缓解策略就是覆盖最早的半开式连接。这种策略要求合法连接可以在比积压时间(恶意填充恶意SYN数据包的)更短的时间内建立连接。当攻击量增加时,或者如果积压量太小而不实际,这种特定的防御就会失败。

SYN cookie

我们知道,TCP协议开辟了一个比较大的内存空间backlog队列来存储半连接条目,当SYN请求不断增加,并这个空间,致使系统丢弃SYN连接。为使半连接队列被塞满的情况下,服务器仍能处理新到的SYN请求,SYN cookies技术被设计出来。

SYN cookies应用于linux、FreeBSD等操作系统,当半连接队列满时,SYNcookies并不丢弃SYN请求,而是通过加密技术来标识半连接状态。

在TCP实现中,当收到客户端的SYN请求时,服务器需要回复SYN+ACK包给客户端,客户端也要发送确认包给服务器。通常,服务器的初始序列号由服务器按照一定的规律计算得到或采用随机数,但在SYN cookies中,服务器的初始序列号是通过对客户端IP地址、客户端端囗、服务器IP地址和服务器端囗以及其他一些安全数值等要素进行hash运算,加密得到的,称之为cookie。

当服务器遭受SYN攻击使得backlog队列满时,服务器并不拒绝新的SYN请求,而是回复cookie(回复包的SYN序列号)给客户端, 如果收到客户端的ACK包,服务器将客户端的ACK序列号减去1得到cookie比较值,并将上述要素进行一次hash运算,看看是否等于此cookie。如果相等,则直接完成三次握手

网关超时设置:

防火墙设置SYN转发超时参数(状态检测的防火墙可在状态表里面设置),该参数远小于服务器的timeout时间。当客户端发送完SYN包,服务端发送确认包后(SYN+ACK),防火墙如果在计数器到期时还未收到客户端的确认包(ACK),则往服务器发送RST包,以使服务器从队列中删去该半连接。值得注意的是,网关超时参数设置不宜过小也不宜过大,超时参数设置过小会影响正常的通讯,设置太大,又会影响防范SYN攻击的效果,必须根据所处的网络应用环境来设置此参数。

http和https区别

HTTP是超文本传输协议,运行在TCP之上,明文传输,数据都是未加密的,安全性较差,HTTPS数据传输过程是加密的,安全性较好。

使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy 和 GlobalSign 等。

HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。

http 和 https 使用的是完全不同的连接方式,http的连接很简单,是无状态的,HTTPS 其实就是建构在 SSL/TLS 之上的 HTTP 协议,所以,要比较 HTTPS 比 HTTP 要更耗费服务器资源,用的端口也不一样,前者是 80,后者是 443。

https是HTTP运行在SSL/TLS之上,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。此外客户端可以验证服务器端的身份,如果配置了客户端验证,服务器方也可以验证客户端的身份。

传输层安全协议(TLS)

SSL 代表安全套接字层。它是一种用于加密和验证应用程序(如浏览器)和 Web 服务器之间发送的数据的协议。

(1)客户端向服务器端发起 SSL 连接请求;

(2) 服务器把公钥发送给客户端,并且服务器端保存着唯一的私钥;

(3)客户端用公钥对双方通信的对称秘钥进行加密,并发送给服务器端;

(4)服务器利用自己唯一的私钥对客户端发来的对称秘钥进行解密;

(5)进行数据传输,服务器和客户端双方用公有的相同的对称秘钥对数据进行加密解密,可以保证在数据收发过程中的安全,即是第三方获得数据包,也无法对其进行加密,解密和篡改。

HTTP/1.1 和 HTTP/2 都是基于 TCP 传输协议的,而 HTTP/3 是基于 UDP 传输协议的。

HTTP/3

HTTP/3 是在 QUIC 基础上发展起来的,其底层使用 UDP 进行数据传输,上层仍然使用 HTTP/2。在 UDP 与 HTTP/2 之间存在一个 QUIC 层,其中 TLS 加密过程在该层进行处理。HTTP/3 主要有以下几个特点:

① 使用 UDP 作为传输层进行通信;

② 在 UDP 之上的 QUIC 协议保证了 HTTP/3 的安全性。QUIC 在建立连接的过程中就完成了 TLS 加密握手;

③ 建立连接快,正常只需要 1 RTT 即可建立连接。如果有缓存之前的会话信息,则直接验证和建立连接,此过程 0 RTT。建立连接时,也可以带有少量业务数据;

④ 不和具体底层连接绑定,QUIC 为每个连接的两端分别分配了一个唯一 ID,上层连接只认这对逻辑 ID。网络切换或者断连时,只需要继续发送数据包即可完成连接的建立;

⑤ 使用 QPACK 进行头部压缩,因为 在 HTTP/2 中的 HPACK 要求传输过程有序,这会导致队头阻塞,而 QPACK 不存在这个问题。

 

对称加密,非对称加密

对称密钥(Symmetric-key algorithm)又称为共享密钥加密,加密和解密使用相同的密钥。常见的对称加密算法有DES、3DES、AES、RC5、RC6。对称密钥的优点是计算速度快,但是它有缺点,接收者需要发送者告知密钥才能解密,因此密钥如何安全的发送给接收者成为了一个问题。

非对称加密,公开密钥加密(public-key cryptography)简称公钥加密,这套密码算法包含配对的密钥对,分为加密密钥和解密密钥。发送者用加密密钥进行加密,接收者用解密密钥进行解密。加密密钥是公开的,任何人都可以获取,因此加密密钥又称为公钥(public key),解密密钥不能公开,只能自己使用,因此它又称为私钥(private key)。常见的公钥加密算法有 RSA。

虽然公钥加密解决了密钥配送的问题,但是你没法确认公钥是不是合法的,Bob 发送的公钥你不能肯定真的是 Bob 发的,因为也有可能在 Bob 把公钥发送给 Alice 的过程中出现中间人攻击,把真实的公钥掉包替换。而对于 Alice 来说完全不知。还有一个缺点是它的运行速度比对称加密慢很多。

HTTP/1.X 和 HTTP/2.0 的区别

相比于 HTTP/1.X 的文本(字符串)传送, HTTP/2.0 采用二进制传送。客户端和服务器传输数据时把数据分成帧,帧组成了数据流,流具有流 ID 标识和优先级,通过优先级以及流依赖能够一定程度上解决关键请求被阻塞的问题。

HTTP/2.0 支持多路复用。因为流 ID 的存在, 通过同一个 HTTP 请求可以实现多个 HTTP 请求传输,客户端和服务器可以通过流 ID 来标识究竟是哪个流从而定位到是哪个 HTTP 请求。

HTTP/2.0 头部压缩。HTTP/2.0 通过 gzip 和 compress 压缩头部然后再发送,同时通信双方会维护一张头信息表,所有字段都记录在这张表中,在每次 HTTP 传输时只需要传头字段在表中的索引即可,大大减小了重传次数和数据量。

HTTP/2.0 支持服务器推送。 服务器在客户端未经请求许可的情况下,可预先向客户端推送需要的内容,客户端在退出服务时可通过发送复位相关的请求来取消服务端的推送。

域名解析查询的两种方式

递归查询:如果主机所询问的本地域名服务器不知道被查询域名的 IP 地址,那么本地域名服务器就以 DNS 客户端的身份,向其他根域名服务器继续发出查询请求报文,即替主机继续查询,而不是让主机自己进行下一步查询,如上图步骤(1)和(10)。

迭代查询:当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的 IP 地址,要么告诉本地服务器下一步应该找哪个域名服务器进行查询,然后让本地服务器进行后续的查询,如上图步骤(2)~(9)。

Nginx负载均衡策略

1、轮询

最基本的配置方法,上面的例子就是轮询的方式,它是upstream模块默认的负载均衡默认策略。每个请求会按时间顺序逐一分配到不同的后端服务器。

2、weight

权重方式,在轮询策略的基础上指定轮询的几率

3、ip_hash

指定负载均衡器按照基于客户端IP的分配方式,这个方法确保了相同的客户端的请求一直发送到相同的服务器,以保证session会话。这样每个访客都固定访问一个后端服务器,可以解决session不能跨服务器的问题

4、least_conn

把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。

5、第三方策略

第三方的负载均衡策略的实现需要安装第三方插件。

①fair

按照服务器端的响应时间来分配请求,响应时间短的优先分配。

②url_hash

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用

什么是TCP粘包问题?

TCP粘包就是指发送方发送的若干包数据到达接收方时粘成了一包,从接收缓冲区来看,后一包数据的头紧接着前一包数据的尾,出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方。

造成TCP粘包的原因

(1)发送方原因

TCP默认使用Nagle算法(主要作用:减少网络中报文段的数量),而Nagle算法主要做两件事:

只有上一个分组得到确认,才会发送下一个分组

收集多个小分组,在一个确认到来时一起发送

Nagle算法造成了发送方可能会出现粘包问题

(2)接收方原因

TCP接收到数据包时,并不会马上交到应用层进行处理,或者说应用层并不会立即处理。实际上,TCP将接收到的数据包保存在接收缓存里,然后应用程序主动从缓存读取收到的分组。这样一来,如果TCP接收数据包到缓存的速度大于应用程序从缓存中读取数据包的速度,多个包就会被缓存,应用程序就有可能读取到多个首尾相接粘到一起的包。

什么时候需要处理粘包现象?

如果发送方发送的多组数据本来就是同一块数据的不同部分,比如说一个文件被分成多个部分发送,这时当然不需要处理粘包现象

如果多个分组毫不相干,甚至是并列关系,那么这个时候就一定要处理粘包现象了

如何处理粘包现象?

(1)发送方

对于发送方造成的粘包问题,可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项关闭算法。

(2)接收方

接收方没有办法来处理粘包现象,只能将问题交给应用层来处理。

(2)应用层

应用层的解决办法简单可行,不仅能解决接收方的粘包问题,还可以解决发送方的粘包问题。

解决办法:循环处理,应用程序从接收缓存中读取分组时,读完一条数据,就应该循环读取下一条数据,直到所有数据都被处理完成,但是如何判断每条数据的长度呢?

格式化数据:每条数据有固定的格式(开始符,结束符),这种方法简单易行,但是选择开始符和结束符时一定要确保每条数据的内部不包含开始符和结束符。

发送长度:发送每条数据时,将数据的长度一并发送,例如规定数据的前4位是数据的长度,应用层在处理时可以根据长度来判断每个分组的开始和结束位置。

UDP会不会产生粘包问题呢?

TCP为了保证可靠传输并减少额外的开销(每次发包都要验证),采用了基于流的传输,基于流的传输不认为消息是一条一条的,是无保护消息边界的(保护消息边界:指传输协议把数据当做一条独立的消息在网上传输,接收端一次只能接受一条独立的消息)。

UDP则是面向消息传输的,是有保护消息边界的,接收方一次只接受一条独立的信息,所以不存在粘包问题。

举个例子:有三个数据包,大小分别为2k、4k、6k,如果采用UDP发送的话,不管接受方的接收缓存有多大,我们必须要进行至少三次以上的发送才能把数据包发送完,但是使用TCP协议发送的话,我们只需要接受方的接收缓存有12k的大小,就可以一次把这3个数据包全部发送完毕。

Cookie和session

区别

  1. 安全性: 由于Session 是存储在服务器端的,Cookie 是存储在客户端的,所以Cookie被盗用的可能性相较于Session会更高一些。
  2. 存取值的类型不同:Cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。
  3. 存储大小不同: 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。

登录态

1)、sessionid

登录的时候,服务器生成一个sessionid返回给客户端,客户端记住这个sessionid,然后每次请求的时候都把这个sessionid一起发送过来,就能区分出谁是谁了,但前提是服务器必须记住所有的sessionid。

2)、token

针对sessionid的弊端(要占用大量服务器资源进行存储)所产生的新的方式。同样是服务端发送一个唯一标识给客户端,然后每次的请求都将这个标识传给服务器进行验证。区别在于,服务端不用存储这个唯一标识。

token出现的原因:

是为了解决sessionId占用存储空间的,token在服务器时可以不用存储用户信息的,token传递的方式也不限于cookie传递。

token的生成方式:

浏览器第一次访问服务器时,会传过来一个唯一表示ID,服务端通过算法,加密钥,生成一个token。通过BASE64编码后将token发送给客户端。(服务器端并不进行保存)

客户端将token保存起来,下次请求带着token,服务器收到请求会用相同的算法取验证toekn,如果通过就继续执行。

token组成:

uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库

缺点:

加密过程会花费时间

优点:

服务器不需要记录任何东西,每次都是一个无状态的请求,每次都是通过解密来验证是否合法。不占用存储空间

token验证请求过程:

1、用户登录时,发送用户名和密码到服务端;

2、服务端验证用户名和密码的正确性;

3、验证通过,返回一个带有签名的token给客户端;

4.客户端cookie存储token,并且之后每次发送请求时都将这个token放到header中;

5、服务端接收到请求,并且拿到token,进行签名验证,然后返回信息给客户端

再次访问时服务器端对token值的处理:服务器对浏览器传来的token值进行解密,解密完成后进行用户数据的查询,如果查询成功,则通过认证,实现状态保持,所以,即时有了多台服务器,服务器也只是做了token的解密和用户数据的查询,它不需要在服务端去保留用户的认证信息或者会话信息,这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利,解决了session扩展性的弊端。

HTTP Header

http header 消息通常被分为4个部分:general header, request header, response header, entity header。但是这种分法就理解而言,感觉界限不太明确。根据维基百科对http header内容的组织形式,大体分为Request和Response两部分

1,Request Headers请求头
Accept:客户端可以接受的媒体资源类型,如text/html, application/xhtml+xml, application/xml;
Accept-encoding:客户端可以接受的编码方法,即压缩方法,如gzip、deflate
Accept-Language:客户端可以接受的语言,如en-US、zh-Ch
Cookie:告诉服务器关于 Session 的信息,存储让服务器辨识用户身份的信息。
User-agent:向服务器发送关于浏览器版本的一些信息
Cache-control:控制浏览器的缓存,常见为private、no-cache、max-age、alidate,默认为 private。
Connection:长连接,如keep-alive。
Host:请求的主机名。
Content-Type:发送端发送的实体数据的数据类型。比如,Content-Type:text/html(application/json)表示发送的是html类型。

2. Response Headers响应头

Content-encoding:设置数据使用的编码类型,如gzip;

Content-type:设置响应体的媒体资源类型(MIME),如text/html; charset=UTF-8;multipart/form-data;

Content-length:HTTP消息实体的传输长度;

Age:表明该响应从缓存中拿到时响应的寿命

Expires:设置响应体的过期时间。如果在过期之前进行访问,就会读取缓存中的版本。

Last-modified:设置该文件在服务器端中最后被修改的时间。

GET 和 POST 的区别

get 提交的数据会放在 URL 之后,并且请求参数会被完整的保留在浏览器的记录里,由于参数直接暴露在 URL 中,可能会存在安全问题,因此往往用于获取资源信息。而 post 参数放在请求主体中,并且参数不会被保留,相比 get 方法,post 方法更安全,主要用于修改服务器上的资源。

get 请求只支持 URL 编码,post 请求支持多种编码格式。

get 只支持 ASCII 字符格式的参数,而 post 方法没有限制。

get 提交的数据大小有限制(这里所说的限制是针对浏览器而言的),而 post 方法提交的数据没限制

get 方式需要使用 Request.QueryString 来取得变量的值,而 post 方式通过 Request.Form 来获取。

get 方法产生一个 TCP 数据包,post 方法产生两个(并不是所有的浏览器中都产生两个)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值