● 请你说一下TCP怎么保证可靠性,并且简述一下TCP建立连接和断开连接的过程
参考回答:
TCP保证可靠性:
(1)序列号、确认应答、超时重传
数据到达接收方,接收方需要发出一个确认应答,表示已经收到该数据段,并且确认序号会说明了它下一次需要接收的数据序列号。如果发送发迟迟未收到确认应答,那么可能是发送的数据丢失,也可能是确认应答丢失,这时发送方在等待一定时间后会进行重传。这个时间一般是2*RTT(报文段往返时间)+一个偏差值。
(2)窗口控制与高速重发控制/快速重传(重复确认应答)
TCP会利用窗口控制来提高传输速度,意思是在一个窗口大小内,不用一定要等到应答才能发送下一段数据,窗口大小就是无需等待确认而可以继续发送数据的最大值。如果不使用窗口控制,每一个没收到确认应答的数据都要重发。
使用窗口控制,如果数据段1001-2000丢失,后面数据每次传输,确认应答都会不停地发送序号为1001的应答,表示我要接收1001开始的数据,发送端如果收到3次相同应答,就会立刻进行重发;但还有种情况有可能是数据都收到了,但是有的应答丢失了,这种情况不会进行重发,因为发送端知道,如果是数据段丢失,接收端不会放过它的,会疯狂向它提醒......
(3)拥塞控制
如果把窗口定的很大,发送端连续发送大量的数据,可能会造成网络的拥堵(大家都在用网,你在这狂发,吞吐量就那么大,当然会堵),甚至造成网络的瘫痪。所以TCP在为了防止这种情况而进行了拥塞控制。
慢启动:定义拥塞窗口,一开始将该窗口大小设为1,之后每次收到确认应答(经过一个rtt),将拥塞窗口大小*2。
拥塞避免:设置慢启动阈值,一般开始都设为65536。拥塞避免是指当拥塞窗口大小达到这个阈值,拥塞窗口的值不再指数上升,而是加法增加(每次确认应答/每个rtt,拥塞窗口大小+1),以此来避免拥塞。
将报文段的超时重传看做拥塞,则一旦发生超时重传,我们需要先将阈值设为当前窗口大小的一半,并且将窗口大小设为初值1,然后重新进入慢启动过程。
快速重传:在遇到3次重复确认应答(高速重发控制)时,代表收到了3个报文段,但是这之前的1个段丢失了,便对它进行立即重传。
然后,先将阈值设为当前窗口大小的一半,然后将拥塞窗口大小设为慢启动阈值+3的大小。
这样可以达到:在TCP通信时,网络吞吐量呈现逐渐的上升,并且随着拥堵来降低吞吐量,再进入慢慢上升的过程,网络不会轻易的发生瘫痪。
TCP建立连接和断开连接的过程:
三次握手:
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之间可以开始传输数据了。
四次挥手:
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
1.数据传输结束后,客户端的应用进程发出连接释放报文段,并停止发送数据,客户端进入FIN_WAIT_1状态,此时客户端依然可以接收服务器发送来的数据。
2.服务器接收到FIN后,发送一个ACK给客户端,确认序号为收到的序号+1,服务器进入CLOSE_WAIT状态。客户端收到后进入FIN_WAIT_2状态。
3.当服务器没有数据要发送时,服务器发送一个FIN报文,此时服务器进入LAST_ACK状态,等待客户端的确认
4.客户端收到服务器的FIN报文后,给服务器发送一个ACK报文,确认序列号为收到的序号+1。此时客户端进入TIME_WAIT状态,等待2MSL(MSL:报文段最大生存时间),然后关闭连接。
● 请回答一下HTTP和HTTPS的区别,以及HTTPS有什么缺点?
参考回答:
HTTP协议和HTTPS协议区别如下:
1)HTTP协议是以明文的方式在网络中传输数据,而HTTPS协议传输的数据则是经过TLS加密后的,HTTPS具有更高的安全性
2)HTTPS在TCP三次握手阶段之后,还需要进行SSL 的handshake,协商加密使用的对称加密密钥
3)HTTPS协议需要服务端申请证书,浏览器端安装对应的根证书
4)HTTP协议端口是80,HTTPS协议端口是443
HTTPS优点:
HTTPS传输数据过程中使用密钥进行加密,所以安全性更高
HTTPS协议可以认证用户和服务器,确保数据发送到正确的用户和服务器
HTTPS缺点:
HTTPS握手阶段延时较高:由于在进行HTTP会话之前还需要进行SSL握手,因此HTTPS协议握手阶段延时增加
HTTPS部署成本高:一方面HTTPS协议需要使用证书来验证自身的安全性,所以需要购买CA证书;另一方面由于采用HTTPS协议需要进行加解密的计算,占用CPU资源较多,需要的服务器配置或数目高
● 请你说一说HTTP返回码
1xx:指示信息--表示请求已接收,继续处理。
2xx:成功--表示请求已被成功接收、理解、接受。
3xx:重定向--要完成请求必须进行更进一步的操作。
4xx:客户端错误--请求有语法错误或请求无法实现。
5xx:服务器端错误--服务器未能实现合法的请求。
常见状态代码、状态描述的详细说明如下。
200 OK:客户端请求成功。
206 partial content服务器已经正确处理部分GET请求,实现断点续传或同时分片下载,该请求必须包含Range请求头来指示客户端期望得到的范围
300 multiple choices(可选重定向):被请求的资源有一系列可供选择的反馈信息,由浏览器/用户自行选择其中一个。
301 moved permanently(永久重定向):该资源已被永久移动到新位置,将来任何对该资源的访问都要使用本响应返回的若干个URI之一。
302 move temporarily(临时重定向):请求的资源现在临时从不同的URI中获得,
304:not modified :如果客户端发送一个待条件的GET请求并且该请求以经被允许,而文档内容未被改变,则返回304,该响应不包含包体(即可直接使用缓存)。
403 Forbidden:服务器收到请求,但是拒绝提供服务。
● 请你说一说TCP的三次握手和四次挥手的过程及原因
参考回答:
C-> SYN -> S
S->SYN/ACK->C
C->ACK->S
三次握手的原因:
// 有3中不同的看法:
1. 资源浪费观点:引自《计算机网络》释疑与习题解答 谢希仁
三次握手可以防止已经失效的连接请求报文突然又传输到服务器端导致的服务器资源浪费。例如,客户端先发送了一个SYN,但是由于网络阻塞,该SYN数据包在某个节点长期滞留。然后客户端又重传SYN数据包并正确建立TCP连接,然后传输完数据后关闭该连接。该连接释放后失效的SYN数据包才到达服务器端。在二次握手的前提下,服务器端会认为这是客户端发起的又一次请求,然后发送SYN ,并且在服务器端创建socket套接字,一直等待客户端发送数据。但是由于客户端并没有发起新的请求,所以会丢弃服务端的SYN 。此时服务器会一直等待客户端发送数据从而造成资源浪费。
2. 、可靠性论断:
另外一种是 如果想确定双通道通畅,必须使用三个包的发送接收,也就是三次握手:“这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的.
三次是保证双方互相明确对方能收能发的最低值。理论上讲不论握手多少次都不能确认一条信道是“可靠”的,但通过3次握手可以至少确认它是“可用”的,再往上加握手次数不过是提高“它是可用的”这个结论的可信程度。另外Tcp的可靠传输更多的是靠重传机制来保证的
3. 初始序列号:
TCP建立连接的握手,实质上就是建立一个双向的可靠通信连接,一边一个来回,每一边都自带超时重传来确保可靠性(而不是靠握手的次数)。TCP的3次握手是优化的结果,其实它应该是4次握手,由于是从零开始的建立连接,因此将SYN的ACK以及被动打开的SYN合并成了一个SYN-ACK。
握手的作用,旨在确定两个双向的初始序列号,TCP用序列号来编址传输的字节,由于是两个方向的连接,所以需要两个序列号,握手过程不传输任何字节,仅仅确定初始序列号。
TCP的四次挥手过程如下:
C->FIN->S
S->ACK->C
S->FIN->C
C->ACK->S
四次挥手的原因:由于连接的关闭控制权在应用层,所以被动关闭的一方在接收到FIN包时,TCP协议栈会直接发送一个ACK确认包,优先关闭一端的通信。然后通知应用层,由应用层决定什么时候发送FIN包。应用层可以使用系统调用函数read==0来判断对端是否关闭连接。(也就是说主动关闭的一方在发送FIN之后不再发送数据,但是可能还需要接受数据)
● 请问tcp握手为什么两次不可以?为什么不用四次?
不用四次:
本来握手应该和挥手一样都是需要确认两个方向都能联通的,本来模型应该是:
1.客户端发送syn0给服务器
2.服务器收到syn0,回复ack(syn0+1)
3.服务器发送syn1
4.客户端收到syn1,回复ack(syn1+1)
因为tcp是全双工的,上边的四部确认了数据在两个方向上都是可以正确到达的,但是2,3步没有没有上下的联系,可以将其合并,加快握手效率,所有就变成了3步握手。
● 请你来说一下TCP拥塞控制?
参考回答:
过程cwnd的大小呈指数增长,直到超过慢启动门限,然后进入拥塞避免阶段,cwnd的大小线性增长,当出现网络拥塞(三个重复的ack或者超时)时候,将慢启动门限设置为出现拥塞时候大小的一半,cwnd的大小重新从0开始进入慢启动阶段。
快重传和快恢复:快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期
注意两点:
1. TCP进行拥塞控制的算法有4种,即慢开始、拥塞避免、快重传和快恢复
2. 快重传之后执行的是快恢复而不是慢开始。在点4的时候,不是启动慢启动,而是执行快恢复算法,将门限值和拥塞窗口大小都置为当前拥塞窗口/2,并开始执行拥塞避免算法。
● TCP和UDP的区别和各自适用的场景
参考回答:
1) 连接
TCP是面向连接的传输层协议,即传输数据之前必须先建立好连接。
UDP无连接。
2) 服务对象
TCP是点对点的两点间服务,即一条TCP连接只能有两个端点;
UDP支持一对一,一对多,多对一,多对多的交互通信。
3) 可靠性
TCP是可靠交付:无差错,不丢失,不重复,按序到达。
UDP是尽最大努力交付,不保证可靠交付。
4)拥塞控制,流量控制
TCP有拥塞控制和流量控制保证数据传输的安全性。
UDP没有拥塞控制,网络拥塞不会影响源主机的发送效率。
5) 报文长度
TCP是动态报文长度,即TCP报文长度是根据接收方的窗口大小和当前网络拥塞情况决定的。
UDP面向报文,不合并,不拆分,保留上面传下来报文的边界。
6) 首部开销
TCP首部开销大,首部20个字节。
UDP首部开销小,8字节。(源端口,目的端口,数据长度,校验和)
7)TCP和UDP适用场景
从特点上我们已经知道,TCP 是可靠的但传输速度慢,UDP 是不可靠的但传输速度快。因此在选用具体协议通信时,应该根据通信数据的要求而决定。
若通信数据完整性需让位与通信实时性,则应该选用TCP 协议(如文件传输、重要状态的更新等);反之,则使用 UDP 协议(如视频传输、实时通信等)。
● 2MSL意义:
MSL 是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
1、保证最后一次握手报文能到B,能进行超时重传。
2、2MSL后,这次连接的所有报文都会消失,不会影响下一次连接。
● 请你来说一下GET和POST的区别
参考回答:
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)
2、区别:
1、get参数通过url传递,post放在request body中。
2、get请求在url中传递的参数是有长度限制的,而post没有。
3、get比post更不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息。
4、get请求只能进行url编码,而post支持多种编码方式。
5、get请求会浏览器主动cache,而post支持多种编码方式。
6、get请求参数会被完整保留在浏览历史记录里,而post中的参数不会被保留。
7、GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
8、GET产生一个TCP数据包;POST产生两个TCP数据包。
● 请你来说一下socket编程中服务器端和客户端主要用到哪些函数
参考回答:
为什么在上图中客户端不需要调用bind函数?这是因为如果没有调用bind函数绑定一个端口的话,当调用connect函数时,内核会为该套接口临时选定一个端口,因此可以不用绑定。而服务器之所以需要绑定的原因就是,所以客户端都需要知道服务器使用的哪个端口,所以需要提前绑定。
● 请你说一说TCP/IP数据链路层的交互过程
网络层等到数据链层用mac地址作为通信目标,数据包到达网络等准备往数据链层发送的时候,首先会去自己的arp缓存表(存着ip-mac对应关系)去查找改目标ip的mac地址,如果查到了,就讲目标ip的mac地址封装到链路层数据包的包头。如果缓存中没有找到,会发起一个广播:who is ip XXX tell ip XXX,所有收到的广播的机器看这个ip是不是自己的,如果是自己的,则以单拨的形式将自己的mac地址回复给请求的机器
参考链接:
1. https://www.nowcoder.com/tutorial/93/0cf933dc97be4913b3f5d012eba1e875