面试中协议栈常问的点?
- TCP三次握手过程?
- TCP四次挥手过程?
- 为什么建立连接需要三次握手,断开连接需要四次挥手?
- time_wait状态持续时间及原因?
- 大量的time_wait和close_wait?
- 超时重传和快速重传?
- TCP首部长度有哪些字段?
- TCP在listen时的参数backlog的意义?
- Accept发生在三次握手的哪一步?
- 三次握手过程中有哪些不安全性?
- TCP和UDP的区别?
TCP三次握手四次挥手详解
池式结构
- 线程池
- 内存池
- 连接池
- 请求池
服务端Posix API
- fd = socket();
- bind(); fd —>ip, port
- listen(fd, backlog);
- clientfd = accept(fd, addr, addrlen);
- recv();
- send();
- close();
客户端Posix API
- connect();
epoll Posix API
- epoll_create();
- epoll_ctl();
- epoll_wait();
其他
- shutdown(); (不常用)
- setsockopt(); (UDP)
- getsockopt(); (UDP)
- fctnl(); (控制io阻塞与否)
TCP的三个阶段
- 建立连接
- 传输过程
- 断开连接
UDP主要用在哪里?
- 大量数据传输,下载,例如迅雷VIP下载时,去除了拥塞控制,使其不受流量控制
- 实时性很强的场景,游戏
- DNS协议,例如浏览器请求域名IP时,采用UDP协议,域名服务器的节点与节点之间的数据同步,采用TCP协议
UDP的缺点有哪些?
不稳定
UDP的connect没有传输具体的数据,只是尝试链路是否通畅
TCP数据包头组成
TCP三次握手
- 客户端connect()发出连接请求
- 服务端listen()之后实现第一次握手,listen()将listenfd置为listen的状态,可以进行三次握手
- 第三次握手之后,服务端运行函数accept()
- 如何在syn队列里查到数据包所对应的节点?答:通过五元组(sip, dip, sport, dport, proto)确认
- 节点的生命周期?tcp状态机(11个状态)存到节点里,生命周期到服务端调用close()为止
- 节点也叫做tcp控制块,tcp block,简称tcb
UDP的并发(底层处理)
- 服务端recvfrom(&addr)获取一个客户端的ip和port
- 服务端新建一个fd,sendto(fd, )将ip和port发送给客户端
- 若第一帧混起来了,则将数据直接返回,超时再次重发
- KCP只是基于此框架完成了一层应用协议
TCP数据传输
- tcp如何保证顺序?答:超时重传机制,协议栈接收到一个包启动200ms的定时器,再接收到一个包时重置200ms定时器,以此类推,中间一旦超时,就会从1号包检查有哪些包没有到,假设3号包没到,则从3号包开始依次重发
- tcp缺点:ack确认时间周期长,已经接收到的包的重发的次数多
- 先指数型增长(慢启动),再线性增长发包一定量之后,在现有包的数量基础上降一半再继续增长(拥塞控制)
- 客户端应用程序的send()成功,并不意味着发送数据包成功,这能代表客户端应用程序的数据成功的拷贝到对应协议栈上,调用copy_from_user将数据从用户空间拷贝到协议栈sendbuffer里,write()同理
TCP四次挥手
- 协议栈出现大量的time_wait时该怎么做?答:主动方(主动先调用close的一端)才会产生time_wait 1. 这时查看自己的逻辑;2. 通过setsockopt()设置为reuse(重用),使tcb不被释放而重用,一定程度上减少time_wait
- 协议栈出现大量的close_wait的原因?答:当服务端0 = recv()之后,没有及时close,产生了延迟(可能recv = 0之后有业务代码要处理),可以将业务代码抛给另一个线程进行处理,0 = recv之后,立即close
- 由于服务端0 = recv()之后,没有及时close,导致客户端处于fin_wait_2的状态,有什么方法可以结束这种状态?答:没有,若强行禁止,只能用kill,操作系统进行回收
- 协议栈出现大量的fin_wait_1 的原因?答:客户端没有接收到ack包,导致长期处于fin_wait_1的状态
- 协议栈出现大量的fin_wait_1 该怎么办?答:无解
- 一般不建议调用shutdown(),若做成单向功能,可考虑调用
TCP的11种状态(关联fd)