《TCP/IP详解 卷2:实现》 —1.10.3 UDP输入
1.10.3 UDP输入
UDP输入例程验证UDP首部中的各字段(长度与可选的检验和),然后确定一个进程是否应该接收此数据报。在第23章我们要详细讨论这个检查是如何进行的。一个进程可以接收到一指定UDP端口的所有数据报,或让内核根据源与目标IP地址及源与目标端口号来限制数据报的接收。
在我们的例子中,UDP输入例程从一个全局变量udb(图1-5)开始,查看所有UDP协议控制块链表,寻找一个本地端口号(inp_lport)与接收的UDP数据报的目标端口号匹配的协议控制块。这个PCB是由我们调用socket创建的,它的成员inp_socket指向相应socket结构,并允许接收的数据在此插口排队。
在程序示例中,我们从未为应用程序指定本地端口号。在习题23.3中,我们会看到在写第一个UDP程序时创建一个插口而不绑定一个本地端口号会导致内核自动地给此插口分配一个本地端口号(称为短期端口)。这就是插口的PCB成员inp_lport不是一个空值的原因。
因为这个UDP数据报要传递给我们的进程,发送方的IP地址和UDP端口号被放置到一个mbuf中,这个mbuf和数据(在我们的例子中是26字节)被追加到此插口的接收队列中。图1-11所示的是被追加到这个插口的接收队列中的这两个mbuf。
图1-11 发送方地址和数据
比较这个链表中的第二个mbuf(MT_DATA类型)与图1-10中的mbuf,成员m_len和m_pkthdr.len都减小了28字节(20字节的IP首部和8字节的UDP首部),并且指针m_data也减小了28字节。这有效地将IP和UDP首部删去,只保留了26字节数据追加到插口接收队列。
在链表的第一个mbuf中包括一个16字节Internet插口地址结构,它带有发送方IP地址和UDP端口号。它的类型是MT_SONAME,与图1-6中的mbuf类似。这个mbuf是插口层创建的,将这些信息返回给通过系统调用recvform或recvmsg调用的进程。即使在这个链表的第二个mbuf中有空间(16字节)存储这个插口地址结构,它也必须存放到自己的mbuf中,因为它们的类型不同(一个是MT_SONAME,一个是MT_DATA)。
然后接收进程被唤醒。如果进程处于睡眠状态等待数据的到达(我们例子中的情况),进程被标志为可运行状态等待内核的调度。也可以通过select系统调用或SIGIO信号来通知进程数据的到达。
- 点赞
- 收藏
- 关注作者
评论(0)