【职造便利店】网络面试宝典
2022-08-17 17:12:45 1 举报
计算机网络面试指南
作者其他创作
大纲/内容
网络模型
OSI 参考模型
应用层
表示层
会话层
传输层
网络层
数据链路层
物理层
TCP/IP 协议栈
应用层3
传输层(TCP/UDP)
网际层(IPV4/IPV6)
网络接口层2
TCP
三次握手
客户端的协议栈向服务器端发送了 SYN 包,并告诉服务器端当前发送序列号 j,客户端进入 SYNC_SENT 状态
服务器端的协议栈收到这个包之后,和客户端进行 ACK 应答,应答的值为 j+1,表示对 SYN 包 j 的确认,同时服务器也发送一个 SYN 包,告诉客户端当前我的发送序列号为 k,服务器端进入 SYNC_RCVD 状态
客户端协议栈收到 ACK 之后,使得应用程序从 connect 调用返回,表示客户端到服务器端的单向连接建立成功,客户端的状态为 ESTABLISHED,同时客户端协议栈也会对服务器端的 SYN 包进行应答,应答数据为 k+1
应答包到达服务器端后,服务器端协议栈使得 accept 阻塞调用返回,这个时候服务器端到客户端的单向连接也建立成功,服务器端也进入 ESTABLISHED 状态
四次挥手
TCP 连接终止时,主机 1 先发送 FIN 报文
主机 2 进入 CLOSE_WAIT 状态,并发送一个 ACK 应答,同时,主机 2 通过 read 调用获得 EOF
并将此结果通知应用程序进行主动关闭操作,发送 FIN 报文,进入 LAST_ACK 状态
主机 1 在接收到 FIN 报文后发送 ACK 应答,此时主机 1 进入 TIME_WAIT 状态
而接收到 ACK 的被动关闭方则进入 CLOSED 状态
经过 2MSL 时间之后,主动关闭方也进入 CLOSED 状态
UDP
TCP/UDP 区别
UDP 是一种“数据报”协议,而 TCP 是一种面向连接的“数据流”协议
TCP 是一个面向连接的协议,TCP 在 IP 报文的基础上,增加了诸如重传、确认、有序传输、拥塞控制等能力,通信的双方是在一个确定的上下文中工作的。
而 UDP 则不同,UDP 没有这样一个确定的上下文,它是一个不可靠的通信协议,没有重传和确认,没有有序控制,也没有拥塞控制。我们可以简单地理解为,在 IP 报文的基础上,UDP 增加的能力有限。
UDP 不保证报文的有效传递,不保证报文的有序,也就是说使用 UDP 的时候,我们需要做好丢包、重传、报文组装等工作。
TIME_WAIT
应用服务需要通过发起 TCP 连接对外提供服务。每个连接会占用一个本地端口,当在高并发的情况下,TIME_WAIT 状态的连接过多,多到把本机可用的端口耗尽,应用服务对外表现的症状,就是不能正常工作了。
只有发起连接终止的一方会进入 TIME_WAIT 状态
主机 1 在 TIME_WAIT 停留持续时间是固定的,是最长分节生命期 MSL(maximum segment lifetime)的两倍,一般称之为 2MSL。
为什么不直接进入 CLOSED 状态,而要停留在 TIME_WAIT 这个状态
首先,这样做是为了确保最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭。
TCP 在设计的时候,做了充分的容错性设计,比如,TCP 假设报文会出错,需要重传。在这里,如果图中主机 1 的 ACK 报文没有传输成功,那么主机 2 就会重新发送 FIN 报文。
如果主机 1 没有维护 TIME_WAIT 状态,而直接进入 CLOSED 状态,它就失去了当前状态的上下文,只能回复一个 RST 操作,从而导致被动关闭方出现错误。
现在主机 1 知道自己处于 TIME_WAIT 的状态,就可以在接收到 FIN 报文之后,重新发出一个 ACK 报文,使得主机 2 可以进入正常的 CLOSED 状态。
2MSL
最长分节生命期 MSL(maximum segment lifetime)
2MSL 的时间是从主机 1 接收到 FIN 后发送 ACK 开始计时的;
如果在 TIME_WAIT 时间内,因为主机 1 的 ACK 没有传输到主机 2,主机 1 又接收到了主机 2 重发的 FIN 报文,那么 2MSL 时间将重新计时。
因为 2MSL 的时间,目的是为了让旧连接的所有报文都能自然消亡,现在主机 1 重新发送了 ACK 报文,自然需要重新计时,以便防止这个 ACK 报文对新可能的连接化身造成干扰。
危害
第一是内存资源占用,这个目前看来不是太严重,基本可以忽略。
第二是对端口资源的占用,一个 TCP 连接至少消耗一个本地端口。
优化
net.ipv4.tcp_max_tw_buckets 系统值调小,过于暴力,治标不治本。
调低 TCP_TIMEWAIT_LEN,重新编译系统
SO_LINGER 的设置
如果l_onoff为 0,那么关闭本选项。l_linger的值被忽略,这对应了默认行为,close 或 shutdown 立即返回。如果在套接字发送缓冲区中有数据残留,系统会将试着把这些数据发送出去。
如果l_onoff为非 0, 且l_linger值也为 0,那么调用 close 后,会立该发送一个 RST 标志给对端,该 TCP 连接将跳过四次挥手,也就跳过了 TIME_WAIT 状态,直接关闭。这种关闭的方式称为“强行关闭”。 在这种情况下,排队数据不会被发送,被动关闭方也不知道对端已经彻底断开。只有当被动关闭方正阻塞在recv()调用上时,接受到 RST 时,会立刻得到一个“connet reset by peer”的异常。
net.ipv4.tcp_tw_reuse:更安全的设置
以复用处于 TIME_WAIT 的套接字为新的连接所用。
只适用于连接发起方(C/S 模型中的客户端);
Keep-Alive
定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。
I/O 多路复用
就是在任何一路 I/O 有“事件”发生的情况下,通知应用程序去处理相应的 I/O 事件,这样我们的程序就变成了“多面手”,在同一时刻仿佛可以处理多个 I/O 事件
select
使用 select 函数,通知内核挂起进程,当一个或多个 I/O 事件发生后,控制权返还给应用程序,由应用程序进行 I/O 事件的处理。
ulimit -n
1024(012被占用),最高设置 65535
poll
和 select 相比,它和内核交互的数据结构有所变化,另外,也突破了文件描述符的个数限制
和 select 非常不同的地方在于,poll 每次检测之后的结果不会修改原来的传入值,而是将结果保留在 revents 字段中,这样就不需要每次检测完都得重置待检测的描述字和感兴趣的事件。
和 select 函数对比一下,我们发现 poll 函数和 select 不一样的地方就是,在 select 里面,文件描述符的个数已经随着 fd_set 的实现而固定,没有办法对此进行配置;而在 poll 函数里,我们可以控制 pollfd 结构的数组大小,这意味着我们可以突破原来 select 函数最大描述符的限制,在这种情况下,应用程序调用者需要分配 pollfd 数组并通知 poll 函数该数组的大小。
epoll
epoll 可以说是和 poll 非常相似的一种 I/O 多路复用技术,有些朋友将 epoll 归为异步 I/O,我觉得这是不正确的。本质上 epoll 还是一种 I/O 多路复用技术, epoll 通过监控注册的多个描述字,来进行 I/O 事件的分发处理。不同于 poll 的是,epoll 不仅提供了默认的 level-triggered(条件触发)机制,还提供了性能更为强劲的 edge-triggered(边缘触发)机制。至于这两种机制的区别,我会在后面详细展开。
C10K
如何在一台物理机上同时服务 10000 个用户?这里 C 表示并发,10K 等于 10000。
文件句柄
系统内存
网络带宽
异步 I/O+ 多线程
0 条评论
下一页