加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内核分析 - 网络[十二]:UDP模块 - 收发

发布时间:2016-09-26 03:21:42 所属栏目:Linux 来源:站长网
导读:副标题#e# 内核版本:2.6.34 UDP报文接收 UDP报文的接收可以分为两个部分:协议栈收到udp报文,插入相应队列中;用户 调用recvfrom()或recv()系统调用从队列中取出报文,这里的队列就是sk-sk_receive_queue,它是报文中转的纽带,两部 分的联系如下图所示。

数据已经处理完成,释放取到的路由项rt,如果有IP选项,也释放它。如果发送数据成功,返 回发送的长度len;否则根据错误值err进行错误处理并返回err。

ip_rt_put(rt);     
if (free)     
 kfree(ipc.opt);     
if (!err)     
 return len;     
if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {     
 UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_SNDBUFERRORS, is_udplite);     
}     
return err;

在 “ICMP模块” 中往IP层发送数据使用的是ip_push_pending_frames()。而在UDP模块中往IP层发送数 据使用的是ip_push_pending_frames()。而在UDP模块中往IP层发送数据的udp_push_pending_frames()只是对 ip_push_pending_frames()的封装,主要是增加对UDP的报头的处理。同理,udp_flush_pending_frames()也是,只是它更简单 ,仅仅重置了up->len和up->pending的值,重置后可以开始一个新报文。那么udp_push_pending_frames()封装了哪些处 理呢。

udp_push_pending_frames() 发送数据给IP层

设置udp报头,包括源端口source,目的端口dest,报文长度len 。

uh = udp_hdr(skb);     
uh->source = fl->fl_ip_sport;     
uh->dest = fl->fl_ip_dport;     
uh->len = htons(up->len);     
uh->check = 0;

计算udp报头中的校验和,包括了伪报头、udp报头和报文内容。

if (is_udplite)     
 csum  = udplite_csum_outgoing(sk, skb);     
else if (sk->sk_no_check == UDP_CSUM_NOXMIT) {   /* UDP csum disabled */ 
 skb->ip_summed = CHECKSUM_NONE;     
 goto send;     
} else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ 
 udp4_hwcsum_outgoing(sk, skb, fl->fl4_src, fl->fl4_dst, up->len);     
 goto send;     
} else       /*   `normal' UDP    */ 
 csum = udp_csum_outgoing(sk, skb);     
uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len, sk->sk_protocol, csum);

将报文发送给IP层,这个函数已经分析过了。

err = ip_push_pending_frames(sk);

同样,在发送完报文 后,重置len和pending的值,以便开始下一个报文发送。

up->len = 0;     
up->pending = 0;

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读