免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 8476 | 回复: 31

请教关于UDP的一个问题 [复制链接]

论坛徽章:
0
发表于 2008-08-25 20:37 |显示全部楼层
10可用积分
请教各位,就是在使用UDP进行传输的时候,UDP层会不会对发送的包进行分片?
也即是说我调用了sendto(sockfd, buf, 10000, ...)的话,从应用层到UDP层是10000字节的一个包,那么UDP层会不会对这个包进行分片,使得从UDP层到IP层的时候就成了几个UDP包了。
我刚刚看了一下udp_sendmsg()的代码,而且也想了一下,觉得应该是不会的,UDP层如果对它进行了分片,就会有很大的不稳定性,应该是不会这么设计的!

还希望哪位指点一下,谢谢!

27楼有更新。

[ 本帖最后由 scutan 于 2009-2-18 23:28 编辑 ]

最佳答案

查看完整内容

tcp/ip卷1上说的是IP分片的,但是实现可能在UDP层就分片了,为了效率的原因我看了一下,代码很多,不知下面的有没有错从这段代码中我认为是分片在udp中就结束了,因为udp从路由表中找到了mtu

论坛徽章:
0
发表于 2008-08-25 20:37 |显示全部楼层
tcp/ip卷1上说的是IP分片的,但是实现可能在UDP层就分片了,为了效率的原因
我看了一下,代码很多,不知下面的有没有错

udp_sendmsg:

do_append_data:
    up->len += ulen;
    err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen,
            sizeof(struct udphdr), &ipc, rt,
            corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
    if (err)
        udp_flush_pending_frames(sk);
    else if (!corkreq)
        err = udp_push_pending_frames(sk, up);





ip_append_data:

    while (length > 0) {
        /* Check if the remaining data fits into current packet. */
        copy = mtu - skb->len;
        if (copy < length)
            copy = maxfraglen - skb->len;
        if (copy <= 0) {
            char *data;
            unsigned int datalen;
            unsigned int fraglen;
            unsigned int fraggap;
            unsigned int alloclen;
            struct sk_buff *skb_prev;
alloc_new_skb:
            skb_prev = skb;
            if (skb_prev)
                fraggap = skb_prev->len - maxfraglen;
            else
                fraggap = 0;

            /*
             * If remaining data exceeds the mtu,
             * we know we need more fragment(s).
             */

            datalen = length + fraggap;
            if (datalen > mtu - fragheaderlen)
                datalen = maxfraglen - fragheaderlen;
            fraglen = datalen + fragheaderlen;

            if ((flags & MSG_MORE) &&
                !(rt->u.dst.dev->features&NETIF_F_SG))
                alloclen = mtu;
            else
                alloclen = datalen + fragheaderlen;

            /* The last fragment gets additional space at tail.
             * Note, with MSG_MORE we overallocate on fragments,
             * because we have no idea what fragment will be
             * the last.
             */

            if (datalen == length)
                alloclen += rt->u.dst.trailer_len;

            if (transhdrlen) {
                skb = sock_alloc_send_skb(sk,
                        alloclen + hh_len + 15,
                        (flags & MSG_DONTWAIT), &err);
            } else {
                skb = NULL;
                if (atomic_read(&sk->sk_wmem_alloc) <=
                    2 * sk->sk_sndbuf)
                    skb = sock_wmalloc(sk,
                               alloclen + hh_len + 15, 1,
                               sk->sk_allocation);
                if (unlikely(skb == NULL))
                    err = -ENOBUFS;
            }
            if (skb == NULL)
                goto error;

            /*
             *    Fill in the control structures
             */

            skb->ip_summed = csummode;
            skb->csum = 0;
            skb_reserve(skb, hh_len);

            /*
             *    Find where to start putting bytes.
             */

            data = skb_put(skb, fraglen);
            skb->nh.raw = data + exthdrlen;
            data += fragheaderlen;
            skb->h.raw = data + exthdrlen;

            if (fraggap) {
                skb->csum = skb_copy_and_csum_bits(
                    skb_prev, maxfraglen,
                    data + transhdrlen, fraggap, 0);
                skb_prev->csum = csum_sub(skb_prev->csum,
                              skb->csum);
                data += fraggap;
                skb_trim(skb_prev, maxfraglen);
            }

            copy = datalen - transhdrlen - fraggap;
            if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
                err = -EFAULT;
                kfree_skb(skb);
                goto error;
            }

            offset += copy;
            length -= datalen - fraggap;
            transhdrlen = 0;
            exthdrlen = 0;
            csummode = CHECKSUM_NONE;

            /*
             * Put the packet on the pending queue.
             */

            __skb_queue_tail(&sk->sk_write_queue, skb);
            continue;
        }

        if (copy > length)
            copy = length;

        if (!(rt->u.dst.dev->features&NETIF_F_SG)) {
            unsigned int off;

            off = skb->len;
            if (getfrag(from, skb_put(skb, copy),
                    offset, copy, off, skb) < 0) {
                __skb_trim(skb, off);
                err = -EFAULT;
                goto error;
            }
        } else {
            int i = skb_shinfo(skb)->nr_frags;
            skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
            struct page *page = sk->sk_sndmsg_page;
            int off = sk->sk_sndmsg_off;
            unsigned int left;

            if (page && (left = PAGE_SIZE - off) > 0) {
                if (copy >= left)
                    copy = left;
                if (page != frag->page) {
                    if (i == MAX_SKB_FRAGS) {
                        err = -EMSGSIZE;
                        goto error;
                    }
                    get_page(page);
                     skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
                    frag = &skb_shinfo(skb)->frags[i];
                }
            } else if (i < MAX_SKB_FRAGS) {
                if (copy > PAGE_SIZE)
                    copy = PAGE_SIZE;
                page = alloc_pages(sk->sk_allocation, 0);
                if (page == NULL)  {
                    err = -ENOMEM;
                    goto error;
                }
                sk->sk_sndmsg_page = page;
                sk->sk_sndmsg_off = 0;

                skb_fill_page_desc(skb, i, page, 0, 0);
                frag = &skb_shinfo(skb)->frags[i];
                skb->truesize += PAGE_SIZE;
                atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc);
            } else {
                err = -EMSGSIZE;
                goto error;
            }
            if (getfrag(from, page_address(frag->page)+frag->page_offset+frag->size, offset, copy, skb->len, skb) < 0) {
                err = -EFAULT;
                goto error;
            }
            sk->sk_sndmsg_off += copy;
            frag->size += copy;
            skb->len += copy;
            skb->data_len += copy;
        }
        offset += copy;
        length -= copy;
    }


从这段代码中我认为是分片在udp中就结束了,因为udp从路由表中找到了mtu

论坛徽章:
0
发表于 2008-08-25 20:56 |显示全部楼层
不会,分片我个人认为只有在涉及到IP的时候才会想到。具体您可以参看《TCP/IP详解》,分片机制对于UDP来说是透明的。对分段,分片,按包传输能够准确理解,问题就解决了。欢迎高手继续讨论。

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
发表于 2008-08-25 20:58 |显示全部楼层

回复 #1 scutan 的帖子

应该要分片吧,如果不分的话,超过MTU的UDP包岂不是永远都不可能完整到达目的地了。

论坛徽章:
0
发表于 2008-08-25 20:59 |显示全部楼层
原帖由 linuxkernel.boy 于 2008-8-25 20:56 发表
不会,分片我个人认为只有在涉及到IP的时候才会想到。具体您可以参看《TCP/IP详解》,分片机制对于UDP来说是透明的。对分段,分片,按包传输能够准确理解,问题就解决了。欢迎高手继续讨论。


先谢谢,我也看了详解的卷2,里面没有说是否会分,不知道你能否提供点依据吗?谢谢。

论坛徽章:
0
发表于 2008-08-25 21:00 |显示全部楼层

回复 #3 dreamice 的帖子

MTU的分片应该是在IP层进行的

论坛徽章:
0
发表于 2008-08-25 21:26 |显示全部楼层
google了一下,有个SO_SNDBUF

论坛徽章:
0
发表于 2008-08-25 21:31 |显示全部楼层
原帖由 epegasus 于 2008-8-25 21:26 发表
google了一下,有个SO_SNDBUF


嗯,知道这个,如果我sendto()的字节数小于这个SO_SNDBUF的话应该是不会分片的吧?

论坛徽章:
0
发表于 2008-08-25 21:32 |显示全部楼层
刚刚在网上找了一下,也看了很多别人的贴子,基本上都是说的UDP数据包的分片发生在IP层,UDP层对于数据是不分片的。

下面两个链接有相关内容:
http://www.gamedev.net/community/forums/topic.asp?topic_id=343577
http://solipsis.netofpeers.net/wiki2/index.php/UDP_Fragmentation

[ 本帖最后由 scutan 于 2008-8-25 21:37 编辑 ]

论坛徽章:
2
巨蟹座
日期:2014-03-09 21:37:25射手座
日期:2014-04-16 16:23:03
发表于 2008-08-25 21:46 |显示全部楼层
分片发生在IP层,根据发送接口的MTU进行分片。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP