
目录1、NAT2、代理服务器3、内网穿透4、DNS 和 ICMP5、五种IO模型1、NATNAT 网络地址转换技术主要解决 IPv4 地址不够用的问题是路由器的一个重要功能。它在网络通信过程中将一个IP地址空间的地址转换为另一个IP地址空间的地址即私有地址和公有地址之间的转换。NAT 转换过程NAT 路由器将源地址从 10.0.0.10 替换成全局的 IP 202.244.174.37NAT 路由器收到外部的数据时又会把目标 IP 从 202.244.174.37 替换回10.0.0.10在 NAT 路由器内部有一张自动生成的用于地址转换的表NAPT当 10.0.0.10 第一次向 163.221.120.9 发送数据时就会生成表中的映射关系如果局域网内有多个主机都访问同一个外网服务器那么对于服务器返回的数据中目的 IP 都是相同的因此NAPT需要用IPport 的方式来映射唯一的一台主机。但是由于 NAT 依赖这个转换表所以有诸多限制无法从 NAT 外部向内部服务器建立连接装换表的生成和销毁都需要额外开销通信过程中一旦 NAT 设备异常即使存在热备所有的 TCP 连接也都会断开2、代理服务器代理服务器是一种中间服务器充当客户端与互联网之间的桥梁。| 工作过程当客户在浏览器中设置好代理服务器后使用浏览器访问所有WWW站点的请求都不会直接发给目的主机而是先发给代理服务器。代理服务器接受客户的请求后会向目的主机发出请求并接受目的主机的数据存于代理服务器的硬盘中然后再由代理服务器将客户要求的数据发给客户。如果代理服务器已经缓存了客户所需的数据它会直接将这些数据返回给客户而无需再次向目的主机请求。| 正向代理 反向代理正向代理是指客户端通过代理服务器来访问外部网络资源即正向代理代理的是客户端帮助客户端访问其无法直接访问的服务器资源反向代理是指客户端不知道目标服务器的存在代理服务器位于客户端和目标服务器之间接收来自客户端的请求并将其转发给内部网络上的真实服务器进行处理即反向代理代理的是服务器将外部网络连接请求转发给内部网络上的服务器。3、内网穿透| 原理内网穿透的工作原理主要基于 NAT 技术的逆过程。NAT技术将内部网络的私有IP地址转换为外部网络的公网IP地址实现内部网络与外部网络的通信。但是NAT设备会自动屏蔽非内网主机主动发起的连接这使得从外网发往内网的数据包被NAT设备丢弃。内网穿透技术通过特定的方法如端口映射、反向代理等绕过这一限制实现内外网之间的通信。| 方法端口映射通过在路由器上设置端口映射将内网设备的某个端口映射到公网IP地址的某个端口上从而实现外网访问内网设备的目的。这种方法需要路由器支持端口映射功能并且需要知道内网设备的IP地址和端口号。反向代理在内网中部署一个反向代理服务器该服务器将外网用户的请求转发给内网中的目标设备并将目标设备的响应返回给外网用户。这种方法可以实现对外隐藏内网设备的真实IP地址和端口号增加安全性。内网穿透工具使用专门的内网穿透工具如Frp、NATOOL、花生壳等这些工具通常提供图形化界面和命令行工具简化配置过程。用户只需按照工具的提示进行配置即可实现内网穿透。| 应用远程办公员工可以在家中或其他远程地点通过内网穿透技术访问公司内部网络中的资源和服务实现远程办公。家庭网络访问用户可以通过内网穿透技术访问家庭网络中的NAS设备、智能家居设备等实现远程管理和控制。API服务访问开发者可以将内部网络中的API服务通过内网穿透技术暴露到公网上供外部用户访问和使用。游戏联机在一些需要联机游戏的情况下玩家可以通过内网穿透技术实现不同NAT设备之间的直接通信提高游戏体验和稳定性。注意事项内网穿透涉及到将内网设备暴露在外部网络环境中存在一定的安全风险要保证安全性、稳定性、兼容性、且要严格遵守法律法规。4、DNS 和 ICMPDNS 是一整套从域名映射到 IP 的系统。TCP/IP 中使用 IP 地址和端口号来确定网络上的一台主机的一个程序但是 IP 地址不方便记忆于是就有了一种叫主机名的东西是一个字符串并且使用 hosts 文件来描述主机名和 IP 地址的关系。| 域名解析过程先查询浏览器缓存是否有该域名对应的IP地址。如果浏览器缓存中没有会去计算机本地的hosts文件中查询是否有对应的缓存。如果host文件中也没有则会向本地的DNS服务器比如中国移动发送一个DNS查询请求。如果本地DNS解析器有该域名的ip地址就会直接返回如果没有缓存该域名的解析记录它会向根DNS服务器发出查询请求。根DNS服务器并不负责解析域名但它能告诉本地DNS解析器应该向哪个顶级域.com/.net/.org的DNS服务器继续查询。本地DNS解析器接着向指定的顶级域名DNS服务器发出查询请求。顶级域DNS服务器也不负责具体的域名解析但它能告诉本地DNS解析器应该前往哪个权威DNS服务器查询下一步的信息。本地DNS解析器最后向权威DNS服务器发送查询请求。 权威DNS服务器是负责存储特定域名和IP地址映射的服务器。当权威DNS服务器收到查询请求时它会查找example.com域名对应的IP地址并将结果返回给本地DNS解析器。本地DNS解析器将收到的IP地址返回给浏览器并且还会将域名解析结果缓存在本地以便下次访问时更快地响应。浏览器发起连接 本地DNS解析器已经将IP地址返回给您的计算机您的浏览器可以使用该IP地址与目标服务器建立连接开始获取网页内容。DNS解析是将域名转换为IP地址的过程大致分为以下几步客户端发起请求用户输入域名后系统向本地DNS服务器发送查询。本地DNS迭代查询先查本地缓存若有记录直接返回IP。若无向根DNS服务器查询根服务器返回对应顶级域名如.com、.net的TLD服务器地址。本地DNS再向TLD服务器查询获取该域名的权威DNS服务器地址。最后向权威DNS服务器查询得到域名对应的IP地址如A记录。结果返回与缓存IP地址沿原路返回给客户端同时本地DNS缓存结果以加速后续请求。核心逻辑通过多级服务器根→TLD→权威协作逐步缩小查询范围最终解析域名。递归查询和迭代查询区别递归查询客户端 → 本地 DNS 服务器客户端只负责把问题甩给本地 DNS本地 DNS 必须替客户端跑完全程把最终 IP 带回迭代查询本地 DNS 服务器 → 根/TLD/权威服务器对方只告诉你“下一个该问谁”不直接给结果本地 DNS 需要拿着地址主动去追问下一家也就是说递归和迭代是配合使用的而不是二选一绝大多数互联网场景下客户端只负责发起一次递归查询剩下的苦活累活全由本地 DNS 服务器通过多次迭代查询来完成。既然有缓存为什么有时候改了 DNS 记录要等很久才生效这跟 TTL 机制有关本地 DNS 服务器拿到结果后会缓存起来。你修改域名解析后世界各地还有无数本地 DNS 依然顶着过期的缓存直到TTL 倒计时归零才会去请求新数据这就是为什么 DNS 变更通常提示 “24-48 小时全球生效” 的原因ICMP一个新搭建好的网络往往需要先进行一个简单的测试来验证网络是否畅通。但是 IP协议并不提供可靠传输如果丢包了IP 协议并不能通知传输层是否丢包以及丢包的原因。ICMP 协议是一个网络层协议主要解决的就是这个问题。它的功能是确认 IP 包是否成功到达目标地址通知在发送过程中 IP 包被丢弃的原因ICMP 也是基于 IP 协议工作的但是它并不是传输层的功能因此人们仍然把它归结为网络层协议ICMP 只能搭配 IPv4 使用如果是 IPv6 的情况下需要使用 ICMPv6ping 命令基于 ICMP是在网络层而端口号是传输层的内容在 ICMP 中根本就不关注端口号这样的信息。5、五种IO模型IO 等 拷贝。即在任何 IO 过程中都包含两个步骤第一是等待第二是拷贝。拷贝效率受硬件的限制不容易提高而且在实际的应用场景中等待消耗的时间往往都远远高于拷贝的时间所以要想提高 IO 的效率最核心的办法就是让等待的时间尽量少。高效的IO就是单位时间内“等” 的时间比重越低IO效率越高。阻塞I/O特点进程发起I/O操作后全程阻塞直到数据就绪并完成复制。阻塞 IO 是最常见的 IO 模型。流程应用调用recvfrom。内核等待数据到达若未就绪进程挂起。数据到达后内核复制到用户空间。应用处理数据。优缺点实现简单但资源利用率低无法处理高并发。非阻塞I/O特点进程通过轮询检查I/O状态数据未就绪时立即返回错误。流程应用调用recvfrom若数据未就绪返回EWOULDBLOCK。应用轮询调用recvfrom直到数据就绪。数据就绪后复制到用户空间短暂阻塞。优缺点避免长期阻塞但轮询消耗CPU适用于低负载场景。I/O多路复用特点使用select/poll/epoll监控多个描述符任一就绪时通知应用。流程应用调用select阻塞等待描述符就绪。当某个描述符就绪select返回。应用调用recvfrom读取数据复制阶段可能阻塞。优缺点单线程处理多I/O高并发下高效如epoll但编程复杂度较高。信号驱动I/O特点通过信号如SIGIO通知数据就绪应用异步处理。流程应用注册信号处理函数开启信号驱动。内核数据就绪时发送信号。应用在信号处理函数中调用recvfrom读取数据复制阶段可能短暂阻塞。优缺点减少轮询开销但信号处理复杂适用场景有限如UDP。异步I/O特点内核完成所有操作后通知应用全程无阻塞。流程应用调用aio_read指定缓冲区并立即返回。内核负责数据就绪和复制到用户空间。完成后通过回调或信号通知应用。优缺点高效且资源利用率高但依赖操作系统支持如Linux的io_uring或Windows的IOCP。理解这五种模型有助于根据需求选择合适的I/O策略优化系统性能与资源利用率。| 同步 vs 异步同步I/O前四种模型均需应用主动参与数据复制阶段阻塞或短暂阻塞。异步I/O仅第五种模型由内核完全处理应用无需等待任何阶段。只要参与了IO的过程就是同步IO。| fcntl首先我们需要知道文件描述符默认都是阻塞IO。fcntl函数原型#includeunistd.h#includefcntl.hintfcntl(intfd,intcmd,.../* arg */);根据传入的cmd的不同后面追加的参数也不同。fcntl函数有 5 种功能复制一个现有的描述符cmdF_DUPFD获得/设置文件描述符标记(cmdF_GETFD或F_SETFD)获得/设置文件状态标记(cmdF_GETFL或F_SETFL)获得/设置异步 I/O 所有权(cmdF_GETOWN或F_SETOWN)获得/设置记录锁(cmdF_GETLKF_SETLK或F_SETLKW)阻塞式IO我们可以用第三种功能将一个文件描述符设置为非阻塞#includeiostream#includestring#includeunistd.h#includefcntl.husingnamespacestd;voidSetNonBlock(intfd){intflfcntl(fd,F_GETFL);if(fl0){perror(fcntl);return;}fcntl(fd,F_SETFL,fl|O_NONBLOCK);}intmain(){string tipsPlease Enter# ;charbuffer[1024];SetNonBlock(0);while(true){write(0,tips.c_str(),tips.size());ssize_t nread(0,buffer,sizeof(buffer)-1);if(n0){buffer[n]0;coutecho# bufferendl;}elseif(n0){coutread file end!endl;break;}else{coutread error: nendl;}sleep(1);}return0;}从上面的测试中我们可以得出文件描述符被设置为非阻塞如果我们不输入数据数据一直不就绪则会返回错误-1但是我们还知道read函数读取错误也会返回-1那怎么区分究竟是读取错误还是数据未就绪呢通过errno查找更详细的错误原因。本篇文章的分享就到这里了如果您觉得在本文有所收获还请留下您的三连支持哦~