【面试题】计算机网络
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数据包(seq=x 随机32位序列号),进入SYN_SENT状态
- 服务器检测SYN的值是否为1,收到客户端连接请求。向客户端发送一个ACK标志位(=1),确认号ack=x+1;同时自己也发送一个SYN标志位=1,seq=y 即SYN+ACK包,此时服务器进入SYN_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状态。
【报文最长的寿命时间:2MSL】
5、TCP和UDP
TCP:传输控制协议
UDP:用户数据报协议
- 需要资源少,网络情况稳定的内网,或者对于丢包不敏感的应用,比如 DHCP 就是基于 UDP 协议的。
- 不需要一对一沟通,建立连接,而是可以广播的应用。因为它不面向连接,所以可以做到一对多,承担广播或者多播的协议。
- 需要处理速度快,可以容忍丢包,但是即使网络拥塞,也毫不退缩,一往无前的时候

TCP应用场景:
UDP应用场景:
- 直播:直播对实时性的要求比较高,宁可丢包,也不要卡顿的,所以很多直播应用都基于 UDP 实现了自己的视频传输协议
- 实时游戏:游戏的特点也是实时性比较高,在这种情况下,采用自定义的可靠的 UDP 协议,自定义重传策略,能够把产生的延迟降到最低,减少网络问题对游戏造成的影响
- 物联网:一方面,物联网领域中断资源少,很可能知识个很小的嵌入式系统,而维护 TCP 协议的代价太大了;另一方面,物联网对实时性的要求也特别高。比如 Google 旗下的 Nest 简历 Thread Group,推出了物联网通信协议 Thread,就是基于 UDP 协议的
- 数据包总量比较少的通信,比如DNS、SNMP。
- 视频、音频等对实时性要求比较高的多媒体通信。
- 广播通信、多播通信。
## 参考文章: https://blog.csdn.net/zhang6223284/article/details/81414149
6、TCP
(1)TCP如何保证可靠?
- TCP给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层
- 流量控制:TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端数据所能接收的数据量。可以降低发送的速率,防止包丢失。【滑动窗口协议】
- 拥塞控制:当网络拥塞时,减少数据的发送
- 校验和:检测数据在传输过程中的任何变化,如何收到段的校验和有差错,TCP将丢弃这个报文段和不确认收到次报文段【TCP会丢弃重复的数据】
- 停止传输协议:每发完一个分组就停止发送,等待对方确认接收。在收到确认后再发送下一个分组。【超时重传:当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。】
(2)TCP的滑动窗口影响了什么性能?
- 改善了网络的吞吐量:容许发送方在接收任何应答之前传送附加的包。接收方告诉发送方在某一时刻能送多少包(称窗口尺寸)。
【吞吐量:单位时间内成功地传送数据的数量】
- 实现流量控制:如果滑动窗口过小,则需要在网络上频繁的传输确认信息,占用了大量的网络带宽;如果滑动窗口过大,对于利用率较高,容易产生丢包现象的网络,则需要多次发送重复的数据,也同样耗费了网络带宽
(3)TCP的粘包怎么解决?
1、粘包:
应用程序所看到的数据是一个整体,或说是一个流,一条消息有多少字节对应用程序是不可见的【TCP协议是面向流的协议】,这也是容易出现粘包问题的原因。
UDP是面向消息的协议,每个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据
2、怎样定义消息:
可以认为一次性write/send的数据为一个消息【无论底层怎样分段分片,TCP协议层会把构成整条消息的数据段排序完成后才呈现在内核缓冲区。】
3、出现粘包的原因:
因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
1)客户端发:消息A,消息B ==> 消息A,消息B
2)客户端发:消息A,消息B ==> 消息A,消息A+B (消息A太大了 || 服务器不及时接收缓冲区的包,服务端下次再收的时候还是从缓冲区拿上次遗留的数据)
3)客户端发:消息A,消息B ==> 消息A+B,消息B (消息A太小了,TCP为了提高传输效率,等缓冲区满才发送出去)
4)客户端发:消息A,消息B ==> 消息A+B(消息A和B都太小了,TCP为了提高传输效率,将消息A和B粘包一起发送)
4、粘包的解决方法:
接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓,然后接收端来一个死循环接收完所有数据
1)在两次send之间调用usleep休眠小一段时间来解决【缺点:传输效率大大降低,而且也并不可靠】
2)对数据包进行封包和解包:发送消息的时候,给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。【缺点:会放大网络延迟带来的性能损耗】
3)发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
4)在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。
(4)TCP为什么有time_wait状态?
由于主动关闭方要等待被动关闭方接收到ACK包,报文最长的寿命时间为2MSL,如果在2MSL内被动关闭方没有接收到ACK包,会再次重发FIN包,这是一个等待机制。
在经过2MSL事件后,主动关闭方才撤销TCB,进入CLOSE状态。
(5)TCP能有多少个连接
系统用一个4四元组来唯一标识一个TCP连接:{local ip, local port,remote ip,remote port}
客户端(理论值):client发起TCP请求时会绑定一个端口,该端口是独占的,不能和其他TCP连接共享
端口的数据结构是unsigned short,端口0不能使用,所以216-1=65535 = TCP理论最大连接数
服务器端(理论值):最大TCP连接 = 客户端IP数×客户端PORT数 ≈ 232(ip最大值) × 216(port最大值) ≈ 248
实际值:对server端,通过增加内存、修改最大文件描述符个数等参数,单机最大并发TCP连接数超过10万是没问题的
## 参考文章 :https://www.cnblogs.com/simplepaul/p/7865836.html
(6)TCP三次握手之前需要什么(ARP解析和IP寻址)
创建套接字【socket】,绑定端口【bind】,准备监听【listen(套接字,等待连接队列的最长长度)】
网络:两主机要通信传送数据时,就要把应用数据封装成IP包,然后再交给下一层数据链路层继续封装成帧;之后根据MAC地址才能把数据从一台主机,准确无误的传送到另一台主机。
ARP解析:数据链路层,通过IP寻找对方的MAC地址
IP寻址:网络层,根据目的IP地址,找到目的网络
(7)TCP第三次握手的作用是什么?
完成了TCP的全双工通信连接,打通了服务器到客户端的通信通道
(8)TCP连接建立之后呢?
1、TCP连接之后就可以进行通信了,客户端到服务器端的通信,服务器端到客户端的通信。
2、连接之后网线断了:select,epoll监测不到断开或错误事件,对于服务端来说会一直维持着这个连接。
如果网线断开的时间短暂,在SO_KEEPALIVE设定的探测时间间隔内,并且两端在此期间没有任何针对此长连接的网络操作。当连上网线后此TCP连接可以自动恢复,继续进行正常的网络操作。
如果网线断开的时间很长,超出了SO_KEEPALIVE设定的探测时间间隔,或者两端期间在此有了任何针对此长连接的网络操作。当连上网线时就会出现ETIMEDOUT或者ECONNRESET的错误。你必须重新建立一个新的长连接进行网络操作。
【 服务器要想知道客户端的意外掉线,需要做心跳包:在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时间间隔发送。
心跳包:定时发送的一个自定义结构体(心跳包或心跳帧),让对方知道自己“在线”。 以确保链接的有效性。
TCP中已经为实现了一个叫做心跳的机制,如果设置了心跳,那TCP就会在一定的时间内发送你设置的次数的心跳,并且此信息不会影响你自己定义的协议。
- 应用层自己实现的心跳包 :启动一个低级别的线程,在该线程中不断检测客户端的回应, 如果在一定时间内没有收到客户端的回应,即认为客户端已经掉线;同样,如果客户端在一定时间内没有收到服务器的心跳包,则认为连接不可用。
- TCP的KeepAlive保活机制:利用TCP/IP协议层为内置的KeepAlive功能来实现心跳功能
】
3、连接之后出现服务器意外掉线之类的错误:例如Qt中监听错误信号QAbstractSocket::error(QAbstractSocket::SocketError socketError),当连接不上服务器的时候,会发送QAbstractSocket::ConnectionRefusedError错误信号,可以进行响应的处理
(9)TCP快重传
发送端在发送数据包之后就开启一个计时器,在一定时间内没有收到对方的ACK报文,则重新发送数据,直到发送成功。
影响超时重传机制协议效率的一个关键参数是重传超时时间(RTO)。
RTO的值被设置过大过小都会对协议造成不利影响。
- RTO设长了,重发就慢,没有效率,性能差。
- RTO设短了,重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。
连接往返时间(RTT),指发送端从发送TCP包开始到接收它的立即响应所消耗的时间。
(10)TCP连接中,服务端的socket要做哪些
1、创建socket:int socket(int domain/*IPv4*/, int type/*子协议*/, int protocol/*协议号,一般为0*/);
2、绑定IP和端口号bind:int bind(int sockfd/*套接字*/, const struct sockaddr *addr/*服务器端结构体*/, socklen_t addrlen/*结构体长度*/);
出现无法绑定setsockopt:setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt/*1*/,sizoef(opt));
3、做监听准备listen:int listen(int sockfd/*套接字*/, int backlog/*等待队列的容量*/);
4、被动监听客户端的连接请求并响应accept:int accept(int sockfd/*套接字*/, struct sockaddr *addr/*客户端结构体*/, socklen_t *addrlen/*结构体长度*/);
5、发送数据send:ssize_t send(int sockfd/*套接字*/, const void *buf/*缓存发送的消息*/, size_t len/*缓存大小*/, int flags/*是否阻塞*/);
6、接收数据recv:ssize_t recv(int sockfd/*套接字*/, void *buf/*缓存接收的消息*/, size_t len/*缓存大小*/, int flags/*是否阻塞*/);
7、关闭TCP连接:shutdown:int shutdown(int sockfd, int how/*如何断开连接*/); /*连接就会被立即断开*/
close :int close(int sockfd); /*一次性关掉读写,无法解决多个文件描述符指向了同一个连接时的关闭*/
(11)TCP三次握手的缺点可能引起的危害?
在TCP三次握手的第三步中,如果服务器没有收到客户端的最终ACK确认报文,会一直处于SYN_RECV状态,将客户端IP加入等待列表,并重发第二步的SYN+ACK报文。重发一般进行3-5次,大约间隔30秒左右轮询一次等待列表重试所有客户端。另一方面,服务器在自己发出了SYN+ACK报文后,会
预分配资源为即将建立的TCP连接储存信息做准备,这个资源在等待重试期间一直保留。更为重要的是,服务器资源有限,可以维护的SYN_RECV状态超过极限后就不再接受新的SYN报文,也就是拒绝新的TCP连接建立。
1、DOS攻击:拒绝服务攻击,【服务资源包括网络带宽,文件系统空间容量,开放的进程或者允许的连接。这种攻击会导致资源的匮乏,无论计算机的处理速度多快、内存容量多大、网络带宽的速度多快都无法避免这种攻击带来的后果,使计算机或网络无法提供正常的服务】
最常见的DoS攻击有计算机网络宽带攻击和连通性攻击
-
- 基于卷:向目标发送大量数据包,从而耗尽所有资源。使用的资源可能只是带宽。这些攻击包括ICMP和UDP泛洪。
- 基于协议:这些攻击通常使用服务器的资源,而不是来自服务器的带宽。他们还可以使用服务器外围的网络设备的资源(例如防火墙,入侵检测系统和交换机)。示例包括Smurf攻击(使用欺骗IP的广播IP的ICMP),Fraggle攻击(与Smurf相同,仅使用UDP),SYN泛洪,死亡ping(具有相同目标和源IP和端口的超大ICMP),以及好多其它的。
- 应用层攻击:对服务器的合法应用程序层(第7层)请求的攻击,这些请求旨在使其崩溃。其中包括对Apache HTTP Server和Microsoft IIS的攻击,还包括Slowloris等工具。
2、DDOS攻击:分布式拒绝服务攻击
指借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动DDOS攻击,从而成倍地提高拒绝服务攻击的威力。
(12)TCP的特点
面向连接、可靠的字节流传输
- 面向连接:TCP的连接是全双工的,连接是一对一的
- 字节流传输:发送端执行写操作和接收端执行的读操作直接没有数量关系,TCP将数据先放入缓冲区中,这些数据有可能会粘包
- 可靠:发送应答机制、超时重传机制、滑动窗口机制
(13)TCP如何保证可靠有序的传输?
- 通过三次握手建立连接
- 发送应答机制,也就是将数据发送给对方后,对方必须应答是否发送成功
- 使用“滑动窗口”机制,根据网络的好坏,控制发送的分组数据的大小
- 超时重传机制,发送端在发送TCP数据包之后启动定时器,如果在时间到了还未收到应答,发送端将重新发送数据包
7、select、poll、epoll
以老师给学生回答做例子:
(1)循环服务器模型:服务器再同一时刻只能响应一个客户端的请求
例子:当一个学生来上课,老师一直跟着这名学生,直到它解决问题离开教室,老师才能一直解决下一个学生的问题。
只要有学生进入教室,无论这名学生有没有问题,老师都不能帮助其他同学解决问题,需要等到这名学生离开教室为止
⭐优点:简单易懂,没有同步、加锁等复杂情况,也没有进程创建等开销
-
- UDP循环服务器:每次从套接字上读取一个客户端请求->处理->然后将结果返回给客户端
因为UDP是短连接,没有一个客户端可以一直占用服务端(文件传输除外),服务器可以满足每一个客户端的请求
-
- TCP循环服务器:一次只能处理一个客户端的请求,完成这个客户端的所有请求后才可以断开连接,如果任务没有完成,那么它会一直占用服务器的进程,直到处理完毕之后服务器关闭连接。
(2)并发服务器模型:每一个客户端的请求并不是由服务器直接处理,而且由服务器的子进程/线程来处理,这样服务器可以在同一个时刻响应多个客户端的请求
例子:学校为了解决老师无法同时帮助多个学生解决问题,为每一个学生安排了一名老师进行辅导,但是学校的资源有限,当学生的数量达到一定量时,学校无法承担那么大的开销。
⭐缺点:没有从根本上解决循环服务器处理效率低的问题(学校不能无限制的聘请无数个老师)
没有解决资源利用率低的问题(每位学生不可能一直有问题,但是每个学生都占用了一名老师资源)
-
- 多进程并发服务器模型:改进了TCP循环服务器客户端独占服务器的情况,但是创建多个进程非常消耗资源,系统的进程数也有限制
- 多线程并发服务器模型:改进了多进程并发服务器资源消耗大的问题,但是同时也带来了同步问题,线程不健壮的问题,容易导致整个服务器的崩溃,一个进程能创建的线程数也存在上限
(3)I/O多路复用模型:内核一旦发现进程指定的一个或者多个IO条件准备读取时,它就通知该进程。
例子:由于资源利用率的问题,学校只聘请一名特别资深的教授(具有高端配置的服务器),这名教授处理问题的速度特别快
同时安排一名班长监听每个学生有没有问题,如果有问题,班长就告诉教授,教授就快速的解决这名学生的问题,解决之后进入等待,直到监听到下一名学生出现问题为止
这样,每个学生的问题都能被即时响应和解决,而且没有浪费资源
⭐优点:系统开销小,不必创建和维护进程/线程,从而大大减小了系统的开销,同时解决了线程阻塞的问题(也可以使用到并发服务器的设计中)
【因为socket套接字也是一种文件,socket句柄就是一个文件描述符,所以可以通过数据结构存储这些文件描述符,实现通信的需求】
-
- select:本质是数组【轮询 + 遍历】
⭐优点:跨平台支持性好,几乎在所有平台上都支持
⭐缺点:
- 延展性差:用数fd_set来管理文件描述符,fd_set的本质是数组,所以select监听的个数有最大值【默认1024】
- 数据开销大:每次调用select,都需要把fd_set从用户态拷贝到内核态,影响系统效能
-
- poll:本质是链表【轮询 + 遍历】
⭐优点:解决了select监听个数受限的问题
⭐缺点:需要做从用户态到内核态的转换,和数据拷贝,效率低,然后轮询每个fd的状态,会经历多次无谓的遍历
没有解决select中的性能问题,需要轮询pollfd来获取就绪的文件描述符,但是同一时刻可能只有少数的客户端有请求
-
- epoll:本质是红黑树
⭐优点:不需要做用户区到内核去的转换,数据在共享内存中,epoll维护的红黑树在共享内存中,内核区和用户区共同操作共享内存
(1)三种多路复用IO的区别?
1、select内部用数组实现,poll用链表实现,epoll用红黑树来实现
2、select有最大监听个数的限制,poll和epoll没有
3、select和poll需要做从内核区到用户区的转换,数据拷贝,效率低
epoll不需要,epoll维护的树及其数据都在共享内存中
## 参考资料:老梁 + 肖家宝同学的整理 + 我的笔记
8、linux中文件IO和标准IO的区别
(1)文件IO:不带缓存的IO,也是低级IO,操作系统提供的基本IO服务【不可移植,特定于LINUX平台/UNIX平台】
(2)标准IO:是标准函数包和stdio.h头文件中定义的部分,具有可移植性,提供了三种类型的缓冲区
- 全缓冲区:填满缓冲区才能进行实际的IO操作,可以调用fflush()刷新【普通文件】
- 行缓冲区:当输入或输出遇到换行符时刷新缓冲区,标准IO库执行IO操作【标准输入输出】
- 无缓冲区:【stderr】

## 参考文章:https://blog.csdn.net/big_bit/article/details/51804391
9、HTTP(超文本传输协议)/ HTTPS(安全超文本传输协议)
HTTP
特点:客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
HTTPS = HTTP over SSL/TLS
是一个安全通信通道
HTTP是应用层协议,TCP是传输层协议,在应用层和传输层之间,增加了一个安全套接层SSL(安全套接字层)/TLS(传输层安全协议)
SSL使用40 位关键字作为RC4流加密算法
HTTPS的作用:
-
内容加密 建立一个信息安全通道,来保证数据传输的安全;
-
身份认证 确认网站的真实性
-
数据完整性 防止内容被第三方冒充或者篡改
HTTP和HTTPS的区别:
- HTTPS协议需要到CA申请证书。
- HTTP是超文本传输协议,信息是明文传输;HTTPS则是具有安全性的ssl加密传输协议。
- HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,HTTP是80,HTTPS是443。
- HTTP的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。
## 参考文章:https://blog.csdn.net/WHB20081815/article/details/67640804
10、ARP解析过程
ARP:地址解析协议,ARP协议提供了网络层地址(IP地址)到物理地址(mac地址)之间的动态映射
(1)为什么需要ARP协议
OSI模型把网络工作分为七层,每层互不干扰,只通过接口来进行通信。IP地址在第三层网络层,MAC地址在第二层数据链路层。
协议在发送数据包时,数据包首先是被网卡接收到再去处理上层协议的,所以首先要封装第三层(IP地址)和第二次(MAC地址)的报头,但是协议仅知道目的地址IP地址,不知道MAC地址,但是不能跨层通信
所以需要用到ARP协议
(2)工作过程:
- 每个主机都会在自己的 ARP 缓冲区中建立一个 ARP 列表,以表示 IP 地址和 MAC 地址之间的对应关系。
- 当主机A向主机B发送数据时,先在自己的ARP缓冲表中查看有没有主机B的IP地址
- 若有,则直接查出主机B对应的MAC地址,直接向其发送数据
- 若没有,则更新自己的缓冲区,将主机B与其MAC地址的映射关系更新到自己的ARP缓冲列表中【ARP请求分组,ARP响应分组】
-
- 在本局域网上广播一个ARP请求分组。ARP请求分组的主要内容是表明:我的IP地址是192.168.0.2,我的硬件地址是00-00-C0-15-AD-18,我想知道IP地址为192.168.0.4的主机的硬件地址
- 在本局域网上的所有主机上运行的ARP进行都收到此ARP请求分组
- 主机B在ARP请求分组中看到自己的IP地址,就向主机A发送ARP响应分组,并写入自己的硬件地址。其余的所有主机都不理睬这个ARP请求分组。ARP响应分组的主要内容是表明:“我的IP地址是192.168.0.4,我的硬件地址是08-00-2B-00-EE-AA”【请注意:虽然ARP请求分组是广播发送的,但ARP响应分组是普通的单播,即从一个源地址发送到一个目的地址】
- 主机A收到主机B的ARP响应分组后,就在其ARP缓冲表中写入主机B的IP地址到硬件地址的映射
11、利用ARP和ICMP解释PING命令
- Ping会判断发送的是主机名还是IP地址
- 如果是主机名:【DNS域名解析】调用gethostbyname()解析主机B,将主机名转换成一个32位的IP地址
- Ping向目的IP发送一个ICMP的echo包
- 将目的IP地址转换为48位硬件地址:【ARP协议】在局域网中发送ARP请求分组【广播】
- 主机B收到ARP的请求分组后,将本机硬件地址填充到应答包,发送ARP响应分组给主机A【单播】
- 主机A发送ICMP数据包给主机B
- 主机B收到主机A的ICMP包之后,发送ICMP响应包
- 主机A接收到主机B的ICMP响应包
## 参考文章:https://www.cnblogs.com/alantu2018/p/8472793.html
12、浏览器怎么得到url地址?
URL:统一资源定位符,也就是网络资源的地址
【例子:你要去旅馆找一个人你必须知道他住在那个房间,这时候房间号就是你要找的人对应的地址,也就是这个场景下的URL。】
http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument
http:// 是协议
www.example.com 是域名,表明正在请求哪个WEB服务器
:80 是端口号
/path/to/myfile.html 是网络服务器上资源的路径
key1=value1&key2=value2 是提供给网络服务器的额外参数
#SomewhereInTheDocument 是资源本身的另一部分的锚点(书签)
- URL解析:知道要访问的主机名,端口号以及请求资源的路径
- DNS解析:从URL中解析出IP地址
## 参考文章:https://segmentfault.com/a/1190000016155200
13、在浏览器中输入一串地址发生的过程
14、DNS解析过程
15、C/S模型的代码逻辑
16、IP怎么寻址?
12、OSI七层网络模型中每层的功能
OSI七层模型 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层
TCP/IP五层模型 应用层 传输层 网络层 数据链路层 物理层
TCP/IP四层模型 应用层 传输层 网络层 网络接口层
应用层:为特定应用程序提供数据传输服务。( TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet)
表示层:对上层信息进行变换,保证一个主机应用层信息被另一个主机的应用程序理解,表示层的数据转换包括数据的加密、压缩、格式转换。
会话层:管理主机之间的会话进程,即负责建立、管理、终止。
传输层:提供端对端的接口。( TCP,UDP)
网络层:为数据包选择路由。(IP,ICMP,ARP,RARP)
数据链路层:传输有地址的帧,错误检测功能( SLIP,CSLIP,PPP,ARP,RARP,MTU)
物理层:以二进制数据形式在物理媒体上传输数据。 ISO2110,IEEE802,IEEE802.2

浙公网安备 33010602011771号