TCP协议知识汇总

TCP/IP方面知识整理:


技术面试中常见的网络通信细节问题解答
1. TCP/IP协议栈层次结构

  1. TCP三次握手与四次挥手
    先看三次握手与四次挥手流程图:

1).三次握手细节点
- 三次握手,如果前两次有某一次失败,会重新从第一次开始,重来三次。
- 三次握手,如果最后一次失败,服务器并不会重传ack报文,而是直接发送RTS报文段,进入CLOSED状态。这样做的目的是为了防止SYN洪泛攻击。详情参见TCP第三次握手失败怎么办,即最后一次握手失败。在Linux下可以如下命令检测是否被Syn攻击:netstat -n -p TCP | grep SYN_RECV
- 发起连接时如果发生TCP SYN丢包,那么系统默认的重试间隔是3s,这期间不会返回错误码。
- 如何模拟tcp挥手失败?答案是iptables命令可以过滤数据包,丢弃所有的连接请求,致使客户端无法得到任何ack报文。
2).四次挥手细节点
- 为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到 ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于 LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。总结起来就是保证TCP协议的全双工连接能够可靠关闭保证这次连接的重复数据段从网络中消失
3).为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

  1. TCP与UDP区别
    - TCP UDP
    是否连接 面向连接 无连接
    是否可靠 可靠传输,使用流量控制和拥塞控制 不可靠传输,不使用流量控制和拥塞控制
    传输方式 面向字节流 面向报文
    连接对象个数 只能是一对一通信 支持一对一,一对多,多对一和多对多交互通信
    首部开销 首部最小20字节,最大60字节 首部开销小,仅8字节
    适用场景 适用于要求可靠传输的应用,例如文件传输 适用于实时应用(IP电话、视频会议、直播等)

这里重点说一下可靠性和传输方式的区别。
TCP:每个Tcp socket连接在内核中都有一个发送缓冲区和接收缓冲区,TCP的全双工的工作模式以及TCP的流量(拥塞)控制便是依赖于这两个独立的buffer以及buffer的填充状态。对于接收端,如果应用进程一直没有读取,接收缓冲区满了之后,发生的动作是:收端通知发端,接收窗口关闭(win=0)。这个便是滑动窗口的实现。保证TCP套接口接收缓冲区不会溢出,从而保证了TCP是可靠传输。关于滑动窗口的实现,可以参考这篇文章:一篇带你读懂TCP之“滑动窗口”协议
UDP:没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。如果接收端应用程序来不及从接收缓冲区读取数据导致缓冲区满,也不会通知发送端停止发送,这样就会导致后面的数据包丢失。

  1. linux常见网络模型详解(select、poll与epoll)

参考:
1、一文搞懂TCP与UDP的区别
2、TCP面试常见题:张小方的知乎Live:轻松搞定技术面试中常见的网络通信问题