BSD实现:单播

devtools/2025/2/22 21:29:38/
分用单播数据报

如果程序执行到这里,说明程序并没有执行多播操作,那么大概率是单播。

维护缓存指针

udp_last_inpcb是上一次接收数据报的端口的控制块指针,维护该指针的依据是许多程序往往具有时间局部性,也就是:经常运行的程序下一次往往也还运行,不经常运行的程序下一次大概率不会运行。

迭代全部端口

判断缓存指针指向的是不是现在要找的控制块,如果不是,就调用in_pcblookup函数迭代全部端口。

生成ICMP不可达错误

如果inp为NULL,说明没有找到端口,那么需要生成ICMP错误报告消息。

小结

虽然据TCP/IP卷二中描述,udp_last_inpcb其实没什么用,但笔者看来这里的程序相当巧妙,能从中感受到作者对时间局部性与空间局部性的考虑。inp被复用进行程序流控制,例如inp为NULL时,这说明肯定是进行了寻找操作且没有找到,因为赋值缓存指针必定使inp不为NULL,如果inp匹配缓存指针或者是找到符合的端口,那么生成ICMP错误的代码就直接跳过。

inp这个变量使用register关键字修饰,并被反复使用。可以想象它的值第一次被保存在寄存器后,后面的程序只需要反复操作该寄存器,而不用频繁对其他变量取地址并引用,这对于指令预取和流水线机制都是十分有利的,因为寄存器本身就是速度最快的内存。

(整个UDP协议的代码都写得非常巧妙,精简凝练,对变量的复用不仅能体现全部的控制流,还能体现时间局部性)

	/** Locate pcb for datagram.*/inp = udp_last_inpcb;if (inp->inp_lport != uh->uh_dport ||inp->inp_fport != uh->uh_sport ||inp->inp_faddr.s_addr != ip->ip_src.s_addr ||inp->inp_laddr.s_addr != ip->ip_dst.s_addr) {inp = in_pcblookup(&udb, ip->ip_src, uh->uh_sport,ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD);if (inp)udp_last_inpcb = inp;udpstat.udpps_pcbcachemiss++;}if (inp == 0) {udpstat.udps_noport++;if (m->m_flags & (M_BCAST | M_MCAST)) {udpstat.udps_noportbcast++;goto bad;}*ip = save_ip;ip->ip_len += iphlen;icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);return;}
单播提交数据报给对应端口

程序执行到这里都没有返回,说明并不是多播,但肯定是匹配了上一次的控制块或者是找到了控制块,那么是单播。

返回源站IP地址和端口

还记得我们在应用层定义的sockaddr_in变量吗?在这里会把IP地址和端口保存到这个变量中。

返回控制信息

如果定义了控制选项,那么可以使用udp_saveopt分配一个mbuf缓存控制信息(在这里是IP地址)并返回。

提交数据报到socket的接收队列

这一步可以使用sbappendaddr完成,但是在执行之前,需要修正第一个mbuf,忽略UDP首部和IP首部。提交数据报后,需要使用sorwakeup函数唤醒所有阻塞在接收队列的进程。

	/** Construct sockaddr format source address.* Stuff source address and datagram in user buffer.*/udp_in.sin_port = uh->uh_sport;udp_in.sin_addr = ip->ip_src;if (inp->inp_flags & INP_CONTROLOPTS) {struct mbuf **mp = &opts;if (inp->inp_flags & INP_RECVDSTADDR) {*mp = udp_saveopt((caddr_t) &ip->ip_dst,sizeof(struct in_addr), IP_RECVDSTADDR);if (*mp)mp = &(*mp)->m_next;}
下面宏条件编译的代码还没有实现,暂时忽略
#ifdef notyet/* options were tossed above */if (inp->inp_flags & INP_RECVOPTS) {*mp = udp_saveopt((caddr_t) opts_deleted_above,sizeof(struct in_addr), IP_RECVOPTS);if (*mp)mp = &(*mp)->m_next;}/* ip_srcroute doesn't do what we want here, need to fix */if (inp->inp_flags & INP_RECVRETOPTS) {*mp = udp_saveopt((caddr_t) ip_srcroute(),sizeof(struct in_addr), IP_RECVRETOPTS);if (*mp)mp = &(*mp)->m_next;}
#endif}iphlen += sizeof(struct udphdr);m->m_len -= iphlen;m->m_pkthdr.len -= iphlen;m->m_data += iphlen;if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,m, opts) == 0) {udpstat.udps_fullsock++;goto bad;}sorwakeup(inp->inp_socket);return;
bad:m_freem(m);if (opts)m_freem(opts);
}

http://www.ppmy.cn/devtools/160740.html

相关文章

Spring AI发布!让Java紧跟AI赛道!

1. 序言 在当今技术发展的背景下,人工智能(AI)已经成为各行各业中不可忽视的重要技术。无论是在互联网公司,还是传统行业,AI技术的应用都在大幅提升效率、降低成本、推动创新。从智能客服到个性化推荐,从语…

苍穹外卖day8 地址上传 用户下单 订单支付

地址上传 RestController RequestMapping("/user/addressBook") Api(tags "C端地址簿接口") public class AddressBookController {Autowiredprivate AddressBookService addressBookService;/*** 查询当前登录用户的所有地址信息** return*/GetMapping(&…

使用vue-office报错TypeError: ft.createElementVNode is not a function

支持多种文件(.docx、.xlsx、.xls、.pdf、.pptx)预览的vue组件库,支持vue2/3。也支持非Vue框架的预览。 不支持.doc、.ppt(2003年及以前的版本) 官网:https://www.npmjs.com/package/vue-office/excel?activeTabreadme 官方有实…

Ollmao (OH-luh-毛程序包及源码) 是一款原生 SwiftUI 应用程序,它与 Ollama 集成,可在 Mac 上本地运行强大的 AI 模型

一、软件介绍 文末提供下载 使用 Ollmao 在 Mac 上本地运行强大的 AI 模型 - 这是一款与 Ollama 集成的原生 SwiftUI 应用程序。Ollmao (OH-luh-毛) 是一个与 Ollama 集成的开源项目,但不隶属于 Ollama 团队,也不受 Ollama 团队的…

【python】python文件=注释=书写建议,基于pycharm

一个方法的备注,书写的好; 方便他人查看,方法的作用; 方便不进入方法就能查看,光标移动到方法上就行 方便查看传参,返回值 显得有 逼格吧!,规范化! 建议如下格式书写&…

【MYSQL】视图

【MYSQL】视图 一、视图的概念1.1 视图的概念1.2 为什么要用视图 二、创建视图2.1 创建单表查询视图2.2 创建多表联合视图2.3 基于视图创建视图 三、查询视图3.1 查看数据库的表对象、视图对象3.2 查看视图的结构3.3 查看视图的详细定义信息3.4 展示视图的详细内容 四、修改视图…

springcloudalibaba组件gateway

Spring Cloud Alibaba 组件中的 Gateway 是一个基于 Spring Cloud Gateway 实现的 API 网关,它专为微服务架构提供简单且有效的 API 路由管理方式。以下是对 Spring Cloud Alibaba Gateway 的详细介绍: 一、基本概念 API 网关:作为系统的统…

android,flutter 混合开发,pigeon通信,传参

文章目录 app效果native和flutter通信的基础知识1. 编解码器 一致性和完整性,安全性,性能优化2. android代码3. dart代码 1. 创建flutter_module2.修改 Android 项目的 settings.gradle,添加 Flutter module3. 在 Android app 的 build.gradl…