C++面试题汇总 计算机网络
-
- `TCP`怎么保证可靠性,并且简述一下`TCP`建立连接和断开连接的过程
- `TCP`的模型,状态转移
- `HTTP`和`HTTPS`的区别,以及`HTTPS`有什么缺点?
- `HTTP`返回码
- `IP地址`作用,以及`MAC地址`作用
- 操作系统中的中断
- `OSI七层模型`和`TCP/IP四层模型`,每层列举2个协议
- `TCP`的三次握手和四次挥手的过程及原因
- 搜索`baidu`,会用到计算机网络中的什么层?每层是干什么的
- `TCP`拥塞控制?以及达到什么情况的时候开始减慢增长的速度?
- `TCP/IP`数据链路层的交互过程
- 传递到IP层怎么知道报文该给哪个应用程序,它怎么区分UDP报文还是TCP报文
- 请问你有没有基于做过socket的开发?具体网络层的操作该怎么做?(其实也是问网络编程的基本步骤)
- `TCP`握手为什么两次不可以?为什么不用四次?
- `TCP`拥塞控制
- `TCP`和`UDP`的区别和各自适用的场景
- `TCP`三次握手四次挥手的过程,为什么`TCP`连接握手需要三次,` time_wait`状态
- `HTTP`协议
- GET和POST的区别
- `socket`编程中服务器端和客户端主要用到哪些函数
- 数字证书是什么,里面都包含那些内容
- `UDP`的`connect`函数
- 阻塞,非阻塞,同步,异步
- `Socket`编程的`send() recv() accept() socket()`函数
- `HTTP`协议会话结束标志怎么截出来?
- 粘包和半包问题
TCP
怎么保证可靠性,并且简述一下TCP
建立连接和断开连接的过程
TCP
保证可靠性:序列号
、确认应答
、超时重传
- 数据到达接收方,接收方需要发出一个
确认应答
,表示已经收到该数据段,并且确认序号
会说明了它下一次需要接收的数据序列号。 - 如果发送发迟迟未收到确认应答,那么可能是发送的数据丢失,也可能是确认应答丢失,这时发送方在等待一定时间后会进行重传。
- 这个时间一般是
2*RTT(报文段往返时间) + 一个偏差值
。
- 数据到达接收方,接收方需要发出一个
- 窗口控制与高速重发控制
/
快速重传(重复确认应答)TCP
会利用窗口控制来提高传输速度,意思是在一个窗口大小内,不用一定要等到应答才能发送下一段数据,窗口大小就是无需等待确认而可以继续发送数据的最大值。- 如果不使用窗口控制,每一个没收到确认应答的数据都要重发。使用窗口控制,如果数据段
1001-2000
丢失,后面数据每次传输,确认应答都会不停地发送序号为1001
的应答,表示我要接收1001
开始的数据,发送端如果收到3
次相同应答,就会立刻进行重发; - 但还有种情况有可能是数据都收到了,但是有的应答丢失了,这种情况不会进行重发,因为发送端知道,如果是数据段丢失,接收端不会放过它的,会疯狂向它提醒 …
- 拥塞控制
- 如果把窗口定的很大,发送端连续发送大量的数据,可能会造成网络的拥堵,甚至造成网络的瘫痪。所以
TCP
在为了防止这种情况而进行了拥塞控制。 - 慢启动:定义拥塞窗口,一开始将该窗口大小设为
1
,之后每次收到确认应答(经过一个RTT
),将拥塞窗口大小*2
。 - 拥塞避免:设置慢启动阈值,一般开始都设为
65536
。拥塞避免是指当拥塞窗口大小达到这个阈值,拥塞窗口的值不再指数上升,而是加法增加(每次确认应答/
每个RTT
,拥塞窗口大小+1
),以此来避免拥塞。 - 将报文段的超时重传看做拥塞,则一旦发生超时重传,我们需要先将阈值设为当前窗口大小的一半,并且将窗口大小设为初值
1
,然后重新进入慢启动过程。 - 快速重传:在遇到
3
次重复确认应答(高速重发控制)时,代表收到了3
个报文段,但是这之前的1
个段丢失了,便对它进行立即重传(而不必继续等待设置的重传计数器时间到期)。然后,先将阈值设为当前窗口大小的一半,然后将拥塞窗口大小设为慢启动阈值+3
的大小。- 这样可以达到:在
TCP
通信时,网络吞吐量呈现逐渐的上升,并且随着拥堵来降低吞吐量,再进入慢慢上升的过程,网络不会轻易的发生瘫痪。
- 这样可以达到:在
- 如果把窗口定的很大,发送端连续发送大量的数据,可能会造成网络的拥堵,甚至造成网络的瘫痪。所以
- 参考: TCP 慢启动,拥塞避免,快速重传,快速恢复
- 慢启动
- 定义拥塞窗口,一开始将该窗口大小设为
1
,之后每次收到确认应答(经过一个RTT
),将拥塞窗口大小*2
。
- 定义拥塞窗口,一开始将该窗口大小设为
- 拥塞避免
- 设置慢启动阈值,一般开始都设为
65536
。拥塞避免是指当拥塞窗口大小达到这个阈值,拥塞窗口的值不再指数上升,而是加法增加(每次确认应答/
每个RTT
,拥塞窗口大小+1
),以此来避免拥塞。
- 设置慢启动阈值,一般开始都设为
- 快速重传
-
情况:
- 遇到
3
次重复确认应答ACK
时,代表接收端收到了3
个报文段,但是这之前的1
个段丢失了。此时进行快速重传
- 遇到
-
反应:
- 便对它进行立即重传(而不必继续等待设置的重传计数器时间到期)。
- 先, 将阈值设为当前窗口大小的一半,
- 然后, 将拥塞窗口大小设为慢启动阈值
+3
的大小 - 最后, 重新进入拥塞避免阶段。
- 后来的“快速恢复”算法是在上述的“快速重传”算法后添加的,当收到
3
个重复ACK
时,TCP
最后进入的不是拥塞避免阶段,而是快速恢复阶段。 - 快速重传和快速恢复算法一般同时使用。
- 快速恢复的思想是“数据包守恒”原则,即同一个时刻在网络中的数据包数量是恒定的,只有当“老”数据包离开了网络后,才能向网络中发送一个“新”的数据包,如果发送方收到一个重复的
ACK
,那么根据TCP
的ACK
机制就表明有一个数据包离开了网络,于是cwnd
加1
。 - 如果能够严格按照该原则那么网络中很少会发生拥塞,事实上拥塞控制的目的也就在修正违反该原则的地方。
-
- 快速恢复:
-
当收到
3
个重复ACK
时,把阈值
设置为当前窗口
的一半,把当前窗口
设置为阈值
的值加3
,然后重传丢失的报文段,(加3
的原因是因为收到3
个重复的ACK
,表明有3
个“老”的数据包离开了网络)。 -
再收到重复的
ACK
时,拥塞窗口增加1
。 -
当收到新的数据包的
ACK
时,把cwnd
设置为第一步中的ssthresh
的值。原因是因为该ACK
确认了新的数据,说明从重复ACK
时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态。 -
快速重传针对的是一个包的重传, 快速恢复针对的是恢复一个窗口内的多个包丢失的情况
- 但是可以看出
Reno
的快速重传算法是针对一个包的重传情况的,然而在实际中,一个重传超时可能导致许多的数据包的重传,因此当多个数据包从一个数据窗口中丢失时并且触发快速重传和快速恢复算法时,问题就产生了。 - 因此
NewReno
出现了,它在Reno
快速恢复的基础上稍加了修改,可以恢复一个窗口内多个包丢失的情况。 - 具体来讲就是:
Reno
在收到一个新的数据的ACK
时就退出了快速恢复状态了,- 而
NewReno
需要收到该窗口内所有数据包的确认后才会退出快速恢复状态,从而更一步提高吞吐量。
- 但是可以看出
-
-
TCP
建立连接和断开连接的过程:
-
序列号
seq
:占4
个字节,用来标记数据段的顺序,TCP
把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;- 给字节编上序号后,就给每一个报文段指派一个序号;
- 序列号
seq
就是这个报文段中的第一个字节的数据编号。
-
确认号
ack
:占4
个字节,期待收到对方下一个报文段的第一个数据字节的序号;- 序列号表示报文段携带数据的第一个字节的编号;
- 而确认号指的是期望接收到下一个字节的编号;
- 因此当前报文段最后一个字节的编号
+1
即为确认号。
-
确认
ACK
:占1
位,仅当ACK=1
时,确认号字段才有效。ACK=0
时,确认号无效 -
同步
SYN
:连接建立时用于同步序号。- 当
SYN=1
,ACK=0
时表示:这是一个连接请求报文段。 - 若同意连接,则在响应报文段中使得
SYN=1
,ACK=1
。- 因此,
SYN=1
表示这是一个连接请求,或连接接受报文。
- 因此,
SYN
这个标志位只有在TCP
建产连接时才会被置1
,握手完成后SYN
标志位被置0
。
- 当
-
终止
FIN
:用来释放一个连接。FIN=1
表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接 -
PS
:ACK
、SYN
和FIN
这些大写的单词表示标志位,其值要么是1
,要么是0
;ack
、seq
小写的单词表示序号。
-
三次握手
:Client
将标志位SYN
置为1
,随机产生一个值seq=J
,并将该数据包发送给Server
,Client
进入SYN_SENT
状态,等待Server
确认。Server
收到数据包后由标志位SYN=1
知道Client
请求建立连接,Server
将标志位SYN
和ACK
都置为1
,ack=J+1
,随机产生一个值seq=K
,并将该数据包发送给Client
以确认连接请求,Server
进入SYN_RCVD
状态。Client
收到确认后,- 检查
ack
是否为J+1
,ACK
是否为1
,如果正确则将标志位ACK
置为1
,ack=K+1
,并将该数据包发送给Server
, Server
检查ack
是否为K+1
,ACK
是否为1
,如果正确则连接建立成功,
- 检查
Client
和Server
进入ESTABLISHED
状态,完成三次握手,随后Client
与Server
之间可以开始传输数据了。
-
四次挥手
:- 由于
TCP
连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则 是当一方完成数据发送任务后,发送一个FIN
来终止这一方向的连接,收到一个FIN
只是意味着这一方向上没有数据流动了,即不会再收到数据了 ,但是在这个TCP
连接上仍然能够发送数据,直到这一方向也发送了FIN
。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。 - 数据传输结束后,客户端的应用进程发出连接释放报文段,并停止发送数据,客户端进入
FIN_WAIT_1
状态,此时客户端依然可以接收服务器发送来的数据。 - 服务器接收到
FIN
后,发送一个ACK
给客户端,确认序号为收到的序号+1
,服务器进入CLOSE_WAIT
状态。客户端收到后进入FIN_WAIT_2
状态。 - 当服务器没有数据要发送时,服务器发送一个
FIN
报文,此时服务器进入LAST_ACK
状态,等待客户端的确认 - 客户端收到服务器的
FIN
报文后,给服务器发送一个ACK
报文,确认序列号为收到的序号+1
。此时客户端进入TIME_WAIT
状态,等待2MSL
(MSL
:报文段最大生存时间),然后关闭连接。- 虽然按道理,四个报文都发送完毕,我们可以直接进入
CLOSE
状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK
丢失。 - 所以
TIME_WAIT
状态就是用来重发可能丢失的ACK
报文。 - 在
Client
发送出最后的ACK
回复,但该ACK
可能丢失。Server
如果没有收到ACK
,将不断重复发送FIN
片段。所以Client
不能立即关闭,它必须确认Server
接收到了该ACK
。Client
会在发送出ACK
之后进入到TIME_WAIT
状态。Client
会设置一个计时器,等待2MSL
的时间。如果在该时间内再次收到FIN
,那么Client
会重发ACK
并再次等待2MSL
。 - 所谓的
2MSL
是两倍的MSL(Maximum Segment Lifetime)
。 MSL
指一个片段在网络中最大的存活时间,2MSL
就是一个发送和一个回复所需的最大时间。- 如果直到
2MSL
,Client
都没有再次收到FIN
,那么Client
推断ACK
已经被成功接收,则结束TCP
连接。
- 虽然按道理,四个报文都发送完毕,我们可以直接进入
- 由于
-
TCP
的模型,状态转移
- 四层
TCP/IP
模型如下: