-
TCP和UDP区别
-
TCP是面向连接的协议,发送数据前要先建立连接;UDP是无连接的协议,发送数据前不需要建立连接,是没有可靠性;
-
TCP只支持点对点通信,UDP支持一对一、一对多、多对一、多对多;
-
TCP是面向字节流的,UDP是面向报文的; 面向字节流是指发送数据时以字节为单位,一个数据包可以拆分成若干组进行发送,而UDP一个报文只能一次发完。
-
TCP首部开销(20字节)比UDP首部开销(8字节)要大
-
UDP 的主机不需要维持复杂的连接状态表。
-
运行在TCP 或UDP的应用层协议分析
- 运行在TCP协议上的协议:
- HTTP(Hypertext Transfer Protocol,超文本传输协议),主要用于普通浏览。
- HTTPS(HTTP over SSL,安全超文本传输协议),HTTP协议的安全版本。
- FTP(File Transfer Protocol,文件传输协议),用于文件传输。
- POP3(Post Office Protocol, version 3,邮局协议),收邮件用。
- SMTP(Simple Mail Transfer Protocol,简单邮件传输协议),用来发送电子邮件。
- TELNET(Teletype over the Network,网络电传),通过一个终端(terminal)登陆到网络。
- SSH(Secure Shell,用于替代安全性差的TELNET),用于加密安全登陆用。
- 运行在UDP协议上的协议:
- BOOTP(Boot Protocol,启动协议),应用于无盘设备。
- NTP(Network Time Protocol,网络时间协议),用于网络同步。
- DHCP(Dynamic Host Configuration Protocol,动态主机配置协议),动态配置IP地址。
- 运行在TCP和UDP协议上:
- DNS(Domain Name Service,域名服务),用于完成地址查找,邮件转发等工作。
- ECHO(Echo Protocol,回绕协议),用于查错及测量应答时间(运行在TCP和UDP协议上)。
- SNMP(Simple Network Management Protocol,简单网络管理协议),用于网络信息的收集和网络管理。
- DHCP(Dynamic Host Configuration Protocol,动态主机配置协议),动态配置IP地址。
- ARP(Address Resolution Protocol,地址解析协议),用于动态解析以太网硬件的地址。
-
什么是ARP协议 (Address Resolution Protocol)?
ARP协议完成了IP地址与物理地址的映射。每一个主机都设有一个 ARP 高速缓存,里面有所在的局域网上的各主机和路由器的 IP 地址到硬件地址的映射表。
当源主机要发送数据包到目的主机时,会先检查自己的ARP高速缓存中有没有目的主机的MAC地址,如果有,就直接将数据包发到这个MAC地址,如果没有,就向所在的局域网发起一个ARP请求的广播包(在发送自己的 ARP 请求时,同时会带上自己的 IP 地址到硬件地址的映射),收到请求的主机检查自己的IP地址和目的主机的IP地址是否一致,如果一致,则先保存源主机的映射到自己的ARP缓存,然后给源主机发送一个ARP响应数据包。源主机收到响应数据包之后,先添加目的主机的IP地址与MAC地址的映射,再进行数据传送。如果源主机一直没有收到响应,表示ARP查询失败。
如果所要找的主机和源主机不在同一个局域网上,那么就要通过 ARP 找到一个位于本局域网上的某个路由器的硬件地址,然后把分组发送给这个路由器,让这个路由器把分组转发给下一个网络。剩下的工作就由下一个网络来做。
-
什么是NAT (Network Address Translation, 网络地址转换)
用于解决内网中的主机要和因特网上的主机通信。由NAT路由器将主机的本地IP地址转换为全球IP地址,分为静态转换(转换得到的全球IP地址固定不变)和动态NAT转换。
-
从输入址到获得页面的过程?
-
浏览器查询 DNS,获取域名对应的IP地址:具体过程包括浏览器搜索自身的DNS缓存、搜索操作系统的DNS缓存、读取本地的Host文件和向本地DNS服务器进行查询等。
对于向本地DNS服务器进行查询,如果要查询的域名包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析(此解析具有权威性);
如果要查询的域名不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析(此解析不具有权威性)。
如果本地域名服务器并未缓存该网址映射关系,那么将根据其设置发起递归查询或者迭代查询;
-
浏览器获得域名对应的IP地址以后,浏览器向服务器请求建立链接,发起三次握手;
-
TCP/IP链接建立起来后,浏览器向服务器发送HTTP请求;
-
服务器接收到这个请求,并根据路径参数映射到特定的请求处理器进行处理,并将处理结果及相应的视图返回给浏览器;
-
浏览器解析并渲染视图,若遇到对js文件、css文件及图片等静态资源的引用,则重复上述步骤并向服务器请求这些资源;
-
浏览器根据其请求到的资源、数据渲染页面,最终向用户呈现一个完整的页面。
用到哪些协议?
浏览器中输入一个url发生了什么,用到了哪些协议
三次握手
无须过多赘述,但是有几个重要的问题需要补充。
- 两次握手可以?
假设不采用 “三次握手”,那么只要 server 发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源就白白浪费掉了。
而且,两次握手无法保证Client正确接收第二次握手的报文(Server无法确认Client是否收到),也无法保证Client和Server之间成功互换初始序列号。
- 四次握手?
可以,没必要。
- 第三次握手,客户端的ACK未送达服务器,会怎么样?
这个参考了一些资料后,最合适的应该是分情况讨论:
(1)假定此时双发都没有数据发送,服务端会周期性重传,直到收到A的确认。
(2)假定此时客户端有数据发送,服务端收到数据Data + ACK后,会自动切换状态。
(3)假定服务端有数据发送,数据发送不了,也是一直周期性重传。
四次挥手
-
为什么需要四次挥手来关闭一个TCP连接
四次挥手能够处理延迟的数据包。在网络通信中,由于数据包在传输过程中可能会遇到延迟,因此即使一方已经发送了关闭连接的请求,另一方可能仍然会接收到之前发送的数据包。通过四次挥手的过程,接收方可以确认所有待处理的数据包都已经收到并处理完毕,从而确保数据的完整性。
四次挥手能够解决半关闭状态的问题。半关闭状态是指在一方已经关闭连接,而另一方仍尝试发送数据的情况。通过四次挥手,即使一方已经发送了关闭连接的请求,另一方也可以继续发送数据,直到对方确认收到所有数据并发送关闭连接的请求。这样可以避免数据丢失和连接异常中断的情况。
通过四次交互,双方都能确保对方已经准备好关闭连接,并且所有数据都已经传输完毕,从而实现了连接的可靠关闭。
如果采用三次挥手,可能会导致数据丢失或连接状态不一致的问题。例如,如果客户端发送FIN包后直接关闭连接,而服务端还有未发送完的数据,那么这些数据将丢失。因此,四次挥手是确保TCP连接可靠关闭所必需的。
-
在四次挥手中,为什么客户端在发送FIN之后还要等待一段时间(2MSL)才进入CLOSED状态?(解释TIME-WAIT)
等待2MSL可以确保客户端发送的最后一个ACK报文能够到达服务端。虽然服务端在接收到FIN报文后发送了ACK报文,但由于网络中的数据包可能会丢失或延迟,服务端可能没有收到客户端的ACK确认。因此,客户端等待一段时间,给服务端足够的时间来重新发送ACK报文,以确保服务端能够正确关闭连接。
等待2MSL可以避免已失效的连接请求报文段出现在本连接中。在等待期间,如果有之前发送的数据包由于某种原因延迟到达,客户端可以处理这些迟到的数据包,而不会将其误认为是新连接的数据包,从而保证了数据的完整性和准确性。
等待2MSL还可以确保客户端在发送完最后一个ACK报文后,有足够的时间让该报文在网络中消失,从而避免对新连接造成干扰。这是因为在网络拥塞或其他情况下,报文可能会在网络中存在一段时间,如果客户端立即进入CLOSED状态并开始新的连接,可能会与这些迟到的报文发生冲突。
-
TCP连接中的半连接队列和全连接队列是什么
TCP连接中的半连接队列(也称为SYN队列)用于存储处于TCP三次握手过程中第一步的连接请求。
当服务端收到客户端发起的SYN请求后,内核会把该连接存储到半连接队列中,等待完成三次握手的过程。此时,连接请求还没有完成握手,因此被认为是“半连接”。如果半连接队列满了,新来的连接请求可能会被丢弃或者根据系统配置发送RST报文。
全连接队列就是已经完成三次握手,建立起连接的就会放在全连接队列中。
半连接队列的主要作用是管理并跟踪那些尚未完全建立的连接,确保在三次握手完成之前,这些连接请求能够得到妥善的处理。它是TCP协议保证连接可靠性和性能的重要机制之一。
需要注意的是,当服务端并发处理大量请求时,如果TCP半连接队列过小,就容易出现溢出的情况,导致后续的请求被丢弃,从而影响服务端的请求处理能力。因此,合理设置和调整半连接队列的大小对于优化网络性能和提升系统稳定性具有重要意义。
DNS域名解析过程
- DNS运行于UDP协议之上,使用的端口为53。
1、首先客户端位置是一台电脑或手机,在打开浏览器以后,比如输入http://www.zdns.cn的域名,它首先是由浏览器发起一个DNS解析请求,如果本地缓存服务器中找不到结果,则首先会向根服务器查询,根服务器里面记录的都是各个顶级域所在的服务器的位置,当向根请求http://www.zdns.cn的时候,根服务器就会返回.cn服务器的位置信息。
2、递归服务器拿到.cn的权威服务器地址以后,就会寻问cn的权威服务器,知不知道http://www.zdns.cn的位置。这个时候cn权威服务器查找并返回http://zdns.cn服务器的地址。
3、继续向http://zdns.cn的权威服务器去查询这个地址,由http://zdns.cn的服务器给出了地址:202.173.11.10
4、最终才能进行http的链接,顺利访问网站。
5、这里补充说明,一旦递归服务器拿到解析记录以后,就会在本地进行缓存,如果下次客户端再请求本地的递归域名服务器相同域名的时候,就不会再这样一层一层查了,因为本地服务器里面已经有缓存了,这个时候就直接把http://www.zdns.cn的A记录返回给客户端就可以了。
select,poll,epoll的区别(IO多路复用)
select
-
委托操作系统内核检测服务端的文件描述符(通信和监听两类),因为检测过程会导致阻塞。
-
监听的文件描述符,那么此时调用accept()不会阻塞程序。通信的文件描述符,调用read()/recv()不会阻塞程序。
-
与多进程和多线程相比,I/O多路复用最大优势是系统开销小。
-
最大文件描述符检测数量1024(写死)
#include <sys/select.h>
struct timeval {time_t tv_sec; /* seconds */suseconds_t tv_usec; /* microseconds */
};int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval * timeout);
-
nfds:委托内核检测的这三个集合中最大的文件描述符 + 1。内核需要线性遍历这些集合中的文件描述符,这个值是循环结束的条件,在Window中这个参数是无效的,指定为-1即可。
-
readfds:文件描述符的集合, 内核只检测这个集合中文件描述符对应的读缓冲区,传入传出参数,读集合一般情况下都是需要检测的,这样才知道通过哪个文件描述符接收数据
-
writefds:文件描述符的集合, 内核只检测这个集合中文件描述符对应的写缓冲区,传入传出参数,如果不需要使用这个参数可以指定为NULL
-
exceptfds:文件描述符的集合, 内核检测集合中文件描述符是否有异常状态,传入传出参数,如果不需要使用这个参数可以指定为NULL
-
timeout:超时时长,用来强制解除select()函数的阻塞的,NULL:函数检测不到就绪的文件描述符会一直阻塞。等待固定时长(秒):函数检测不到就绪的文件描述符,在指定时长之后强制解除阻塞,函数返回0。不等待:函数不会阻塞,直接将该参数对应的结构体初始化为0即可。
select文件描述符操作流程:
// 将文件描述符fd从set集合中删除 == 将fd对应的标志位设置为0
void FD_CLR(int fd, fd_set *set);
// 判断文件描述符fd是否在set集合中 == 读一下fd对应的标志位到底是0还是1
int FD_ISSET(int fd, fd_set *set);
// 将文件描述符fd添加到set集合中 == 将fd对应的标志位设置为1
void FD_SET(int fd, fd_set *set);
// 将set集合中, 所有文件文件描述符对应的标志位设置为0, 集合中没有添加任何文件描述符
void FD_ZERO(fd_set *set);
小结:
- 执行原理
(1)将当前的所有文件描述符,一次性从用户态拷贝到内核态
(2)内核中无差别遍历fd(文件描述符)
(3)将所有fd状态从内核态拷贝会用户态
(4)需要用户自己判断哪个fd已经就绪
- 限制和不足
(1)长度有限,最大1024
(2)fdset无法重用,需要循环创建
(3)频繁进行用户态和内核态拷贝
(4)需要对文件描述符列表遍历,O(n)
爱编程的大丙Select
poll
-
poll机制和select类似,一般较少使用(只有select可以跨平台,Linux更多使用epoll)
-
poll检测的文件描述符数量:无上限
#include <poll.h>
// 每个委托poll检测的fd都对应这样一个结构体
struct pollfd {int fd; /* 委托内核检测的文件描述符 */short events; /* 委托内核检测文件描述符的什么事件 */short revents; /* 文件描述符实际发生的事件 -> 传出 */
};struct pollfd myfd[100];
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
来源: 爱编程的大丙 poll
小结:
- 执行原理
(1)将当前的所有文件描述符,一次性从用户态拷贝到内核态
(2)内核中无差别遍历fd(文件描述符)
(3)将所有fd状态从内核态拷贝会用户态
(4)需要用户自己判断哪个fd已经就绪
- 问题和不足
(1)采用pollfd结构数组,没有1024限制
(2)频繁的用户态和内核态切换
(3)顺序便利,O(n)
epoll
-
epoll是select和poll的改进版,底层是红黑树,(select,poll都是线性表机制)不可以跨平台,只可以Linux使用
-
对于待检测集合select和poll是基于线性方式处理的,epoll是基于红黑树来管理待检测集合的。
-
select和poll每次都会线性扫描整个待检测集合,集合越大速度越慢,epoll使用的是回调机制,效率高,处理效率也不会随着检测集合的变大而下降。
-
select和poll工作过程中存在内核/用户空间数据的频繁拷贝问题,在epoll中内核和用户区使用的是共享内存(基于mmap内存映射区实现),省去了不必要的内存拷贝。
-
程序猿需要对select和poll返回的集合进行判断才能知道哪些文件描述符是就绪的,通过epoll可以直接得到已就绪的文件描述符集合,无需再次检测。
-
使用epoll没有最大文件描述符的限制,仅受系统中进程能打开的最大文件数目限制。
epoll工作模式:水平触发(LT),边缘触发(ET)
水平触发(LT)
只要读缓冲区不为空,写缓冲区不满,每次epoll_wait都会返回就绪,是epoll的默认工作方式。
边缘触发(ET)
只有缓冲区的数据有变化,epoll_wait才会返回就绪,因此在ET模式下,每次需要将缓冲区的数据全部读完,不然下次如果缓冲区没有发生数据变化,就一直不会返回就绪了。
小结:
-
epoll_ctl()函数中,每个文件描述符都指定了回调函数,基于回调函数将就绪的文件描述符放入就绪队列,因此时间负责度从O(n)降为O(1);
-
只需要在epoll_ctl()时传递一次文件描述符,epoll_wait()不需要再传递文件描述符。
-
epoll基于红黑树和双列表,没有最大连接限制
-
epoll没有使用MMAP零拷贝技术。
IO多路复用
常见问题搜集
-
socket什么情况下可读?
1.socket接收缓冲区中已经接收的数据的字节数大于等于socket接收缓冲区低潮限度的当前值
2.连接的读一半关闭(即:接收到对方发过来的FIN的TCP连接),并且返回0;
3.socket收到了对方的connect请求已经完成的连接数为非0.这样的soocket处于可读状态;
4.异常的情况下socket的读操作将不会阻塞,并且返回一个错误(-1)。
-
五种IO模型
阻塞IO、非阻塞IO、信号驱动IO、异步IO、I/O复用模型。
IO多路复用
-
TCP/IP状态迁移过程?
TCP/IP状态迁移
参考
TCP、UDP、Socket、HTTP网络编程面试题(总结最全面的面试题!!!) - 非科班的科班的文章 - 知乎
TCP三次握手与四次挥手详解
一张图看懂DNS域名解析全过程 - 玩转Linux内核的文章 - 知乎
来源: 爱编程的大丙 Select