经典网络面试题(4)

16:不使用 listen ,可以建立 TCP 连接吗?

是可以的,客户端是可以自己连自己的形成连接(TCP自连接),也可以两个客户端同时向对方发出请求建立连接(TCP同时打开),这两个情况都有个共同点,就是没有服务端参与,也就是没有listen,就能建立连接。
半连接队列和全连接队列都是在执行 listen 方法时,内核自动创建的。内核还有个全局 hash 表,可以用于存放 sock 连接的信息。在 TCP 自连接的情况中,客户端在 connect 方法时,最后会将自己的连接信息放入到这个全局 hash 表中,然后将信息发出,消息在经过回环地址重新回到 TCP 传输层的时候,就会根据 IP + 端口信息,再一次从这个全局 hash 中取出信息。于是握手包一来一回,最后成功建立连接。

17:没有 accept,能建立 TCP 连接吗?

每一个socket执行listen时,内核都会自动创建一个半连接队列和全连接队列。
第三次握手前,TCP连接会放在半连接队列中,直到第三次握手到来,才会被放到全连接队列中。
accept方法只是为了从全连接队列中拿出一条连接,本身跟三次握手几乎毫无关系。
出于效率考虑,虽然都叫队列,但半连接队列其实被设计成了哈希表,而全连接队列本质是链表。
全连接队列满了,再来第三次握手也会丢弃,此时如果tcp_abort_on_overflow=1,还会直接发RST给客户端。
半连接队列满了,可能是因为受到了SYN Flood攻击,可以设置tcp_syncookies,绕开半连接队列。
客户端没有半连接队列和全连接队列,但有一个全局hash,可以通过它实现自连接或TCP同时打开。

18:用了 TCP 协议,数据一定不会丢吗?

数据从发送端到接收端,链路很长,任何一个地方都可能发生丢包,几乎可以说丢包不可避免。平时没事也不用关注丢包,大部分时候TCP的重传机制保证了消息可靠性。
当你发现服务异常的时候,比如接口延时很高,总是失败的时候,可以用ping或者mtr命令看下是不是中间链路发生了丢包。
TCP只保证传输层的消息可靠性,并不保证应用层的消息可靠性。如果我们还想保证应用层的消息可靠性,就需要应用层自己去实现逻辑做保证。


19:TCP 四次挥手,可以变成三次吗?

为什么 TCP 挥手需要四次呢?
服务器收到客户端的 FIN 报文时,内核会马上回一个 ACK 应答报文,但是服务端应用程序可能还有数据要发送,所以并不能马上发送 FIN 报文,而是将发送 FIN 报文的控制权交给服务端应用程序、
close 函数 粗暴关闭 不会经历完成的 TCP 四次挥手
shutdown 函数 优雅关闭 会经历完成的 TCP 四次挥手
什么情况会出现三次挥手?
当被动关闭方在 TCP 挥手过程中,如果「没有数据要发送」,同时「没有开启 TCP_QUICKACK(默认情况就是没有开启,没有开启 TCP_QUICKACK,等于就是在使用 TCP 延迟确认机制)」,那么第二和第三次挥手就会合并传输,这样就出现了三次挥手。

20:TCP 序列号和确认号是如何变化的?

万能公式,发送的 TCP 报文:
公式一:序列号 = 上一次发送的序列号 + len(数据长度)。特殊情况,如果上一次发送的报文是 SYN 报文或者 FIN 报文,则改为 上一次发送的序列号 + 1。
公式二:确认号 = 上一次收到的报文中的序列号 + len(数据长度)。特殊情况,如果收到的是 SYN 报文或者 FIN 报文,则改为上一次收到的报文中的序列号 + 1。

你可能感兴趣的:(网络,服务器,tcp/ip)