1、TCP拥塞如何控制?
(1)滑动窗口:TCP中采用滑动窗口来进行传输控制,滑动窗口的大小意味着接收方还有多大的缓冲区可以用于接收数据
滑动窗口指出接收缓冲区中的可用空间,从而确保发送方发送的数据不会溢出缓冲区。
窗口时刻动态变化:当接收发送发数据时,窗口大小减小;当接收方从缓冲区中读取数据时,窗口大小增大。
TCP的接收缓冲区满,它必须等待应用程序从这个缓冲区读取数据后才能再接收发送方传来的数据。
UDP不提供流控制,按发送方的速率发送数据,不管接收方的缓冲区是否装得下。
## 参考文献:《UNIX网络编程》
(2)TCP拥塞的原因:在早期的时候,通信的双方不知道网络的状况,所以过程中可能会出现中间节点阻塞丢包,所以就有了滑动窗口机制来解决这个问题。
(3)滑动窗口协议:用于网络数据传输时的流量控制,以避免拥塞的发生。如果过多的发送方同时以很快的速度发送大量的数据包,接收方有可能并没有那么高的接收数据能力,因此极易导致网络的拥塞(并发服务器)。
(4)滑动窗口的值:网络中没有出现拥塞,滑动窗口的值可以增大一些(以便把更多的数据包发送出去);网络出现拥塞,滑动窗口的值应该减小一些(以减少注入到网络中的数据包数)
(5)拥塞控制算法:
- 基于丢包的拥塞控制:将丢包视为出现拥塞,采取缓慢探测的方式,逐渐增大拥塞窗口,当出现丢包时,将拥塞窗口减小,如Reno、Cubic等。
- 基于时延的拥塞控制:将时延增加视为出现拥塞,延时增加时增大拥塞窗口,延时减小时减小拥塞窗口,如Vegas、FastTCP等。
- 基于链路容量的拥塞控制:实时测量网络带宽和时延,认为网络上报文总量大于带宽时延乘积时出现了拥塞,如BBR。
- 基于学习的拥塞控制:没有特定的拥塞信号,而是借助评价函数,基于训练数据,使用机器学习的方法形成一个控制策略,如Remy。
## 参考文章:浅谈TCP拥塞控制算法
2、阻塞IO,非阻塞IO,同步IO,异步IO的区别?
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);- flags:
+ 0:默认设置,此时recv是阻塞接收的,0是常设置的值。
+ MSG_DONTWAIT:非阻塞接收
+ MSG_OOB:接收的是带外数据
+ ...:其它选项
(1)阻塞IO:使用recv的默认参数一直等数据直到拷贝到用户空间,这段时间内进程始终阻塞。
A从宿舍(用户空间)拿着水瓶去饮水机处(内核空间)打水,等到水打满了之后就离开了。若饮水机没有水则一直阻塞等待杯子装满水为止,才离开去做别的事情。(这种IO模型是阻塞+同步的)
(2)非阻塞IO:
改变flags,recv不管有没有获取到数据都返回(如果没有数据那么一段时间后再调用recv看看,如此循环)
B也从宿舍(用户空间)拿着水瓶去饮水机处(内核空间)打水,打开水龙头发现没有水之后离开了(回到用户空间)。
只有是检查无数据的时候是非阻塞的,在数据到达的时候依然要等待复制数据到用户空间(等着水将水杯装满)(这种IO模型是非阻塞+同步的)
(3)同步IO:IO多路复用(select, poll, epoll模型),监听多个IO对象,对象有变化(有数据)的时候就通知用户进程(单个进程可以处理多个socket)
select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。
(4)异步IO:当进程发起IO 操作之后,就直接返回再也不理睬了,直到kernel发送一个信号,告诉进程说IO完成。在这整个过程中,进程完全没有被block。
## 参考文章:简述同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别
3、TCP怎么做到连接的?三次握手,为什么不能两次握手
(1)全双工:通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合。可以同时进行信号的双向传输,A→B和B→A,是瞬时同步的。
(2)TCP连接:要客户端->服务器和服务器->客户端都要建立连接
- 客户端向服务器发送SYN标志位 = 1,seq数据包( 随机32位序列号),进入SYN_SENT״̬
- 服务器检测SYN的值是否为1,收到客户端连接请求。向客户端发送一个ACK标志位(=1),确认号ack=x+1;同时自己也发送一个SYN标志位=1,seq=ySYN_RECV״̬
- 客户端收到服务器的的SYN+ACK包,向服务器发送一个ACK包(ACK标志位,确认号ack=y+1),序列号seq=x+1。此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手
(3)因为TCP的连接是全双工的,应用程序在任何时刻既可以发送数据也可以接收数据。TCP
为了实现可靠数据传输, TCP 协议的通信双方都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。
三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤
如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认
## 参考文章:https://blog.csdn.net/lengxiao1993/article/details/82771768
4、TCP的三次握手和四次挥手
(1)三次握手同上
(2)四次挥手:
- 客户端停止发送数据,向服务器发送FIN包:FIN序列=1,seq=u(u=前面已经传过来的数据的最后一个字节的序号+1)。客户端进入FIN-WAIT-1״̬
- 服务器接收到FIN包,向客户端发出确认报文ACK包:ACK=1,ack=u+1,seq=v。此时服务器进入CLOSE-WAIT(等待关闭)状态。
TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
- 客户端接收服务器的确认请求,客户端进入FIN-WAIT-2(终止等待1)状态,等待服务器发送FIN包(在此之前还要接收服务器发送的最后数据)
- 服务器将最后的数据发送完毕后,向客户端发送FIN包(FIN=1,ACK=1,ack=u+1,服务器可能又发送了一些数据seq=w),服务器进入LAST-ACK(最后确认)状态,等待客户端的确认。
- 客户端收到服务器的FIN包之后,必须发出确认包ACK包(ACK=1,ack=w+1,自己的序号是seq=u+1),客户端进入TIME_WAIT(时间等待)状态,此时TCP连接还未释放,必须经过2MSL后客户端撤销相应的TCP后,才进入CLOSED状态
- 服务器只要收到了客户端的确认包,立即进入CLOSED״̬,撤销TCB之后结束了这次TCP连接。服务器向客户端的方向就被释放了。
客户端->服务器:seq=u;服务器收到谁的FIN,发送ack=u+1;
服务器->客户端:seq=v / seq = w;客户端收到谁的FIN,发送ack=w+1,再发送自己的序列号seq=u+1
(3)TCP四次挥手中TIME-WAIT和CLOSE-WAIT的区别:
CLOSE-WAIT:当被动关闭方接收到主动关闭方发出的FIN包,被动关闭方发出确认ACK包之后,进入CLOSE-WAIT状态,处于半关闭状态,此时主动关闭方没有数据要发送了,但是被动关闭方可能还有数据需要发送,主动关闭方必须接收它的数据。
TIME-WAIT:主动关闭方接收到被动关闭方发出的FIN包,向被动关闭方发出确认ACK包之后,进入TIME-WAIT状态。由于主动关闭方要等待被动关闭方接收到ACK包,报文最长的寿命时间为2MSL,如果在2MSL内被动关闭方没有接收到ACK包,会再次重发FIN包,这是一个等待机制。在经过2MSL事件后,主动关闭方才撤销TCB,进入CLOSE状态。
5、TCP和UDP
(1)TCP
(2)UDP
6、TCP
(1)TCP如何保证可靠?
(2)TCP和滑动窗口影响了什么性能?
(3)TCP的粘包怎么解决?
(4)TCP为什么有time_wait状态?
(5)TCP能有多少个连接
(6)TCP三次握手之前需要什么(ARP解析和IP寻址)
(7)TCP第三次握手的作用是什么?
(8)TCP连接建立之后呢?
(9)TCP快重传
(10)TCP连接中,服务端的socket要做哪些
(11)TCP三次握手的缺点可能引起的危害?
(12)TCP的特点
7、三种多路复用IO的区别?
8、linux IO和标准IO的区别
9、select、poll、epoll
来源:博客园
作者:XieXinBei0318
链接:https://www.cnblogs.com/xiexinbei0318/p/11411752.html