基于最大UDP数据报长度和MTU值的思考

最大UDP数据报长度

   理论上,IP数据报的最大长度是65535字节,这是由IP首部(图IP协议格式)16比特总长度字段所限制。去除20字节的IP首部(图IP协议格式)和8字节的UDP(图UDP协议格式)首部,UDP数据报中用户的最长长度为65507.但是,大多数实现所提供的长度比这个最大值小。

   

   

     我们将遇到两个限制因素。

      第一,应用程序可能会受到其程序接口的限制。socket API提供了一个可供应用程序调用的函数,以设置接收和发送缓存的长度。对于UDP socket,这个长度与应用程序可以读写的最大UDP数据报的长度直接相关。现在的大部分系统都默认提供了可读写大于8192自己的UDP数据报。

      第二个限制来自于TCP/IP的内核实现。可能存在一些实现特性(或差错),使IP数据报长度小于65535字节。

      测试udp最大数据报长度代码

      server.c

      

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>

#define SERVER_PORT 8888
#define MAX_MSG_SIZE 1024

void udps_respon(int sockfd)
{
    struct sockaddr_in addr;
    int addrlen,n;
    char msg[MAX_MSG_SIZE];
    
    while(1){
        /*从网络上读,并写到网络上*/
        bzero(msg,sizeof(msg));   //初始化,置0
        addrlen = sizeof(struct sockaddr);
        n = recvfrom(sockfd,msg,MAX_MSG_SIZE,0,(struct sockaddr*)&addr,&addrlen);   //从客户端接收数据
        msg[n] = '\0';
        /*显示服务端已经收到了消息*/
        fprintf(stdout,"Server have received %s",msg); //显示消息
    } 
}

int main(int argc,char *argv[])
{
    int sockfd;
    struct sockaddr_in addr;
    
    /*建立sockfd描述符*/
        sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if(sockfd < 0){
                fprintf(stderr,"Socket Error:%s\n",strerror(errno));
                exit(1);
        }

    /*服务器端填充sockaddr结构*/
    bzero(&addr,sizeof(struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr=htonl(INADDR_ANY);
    addr.sin_port = htons(SERVER_PORT);
    
    /*捆绑sockfd描述符*/
    if(bind(sockfd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in)) < 0){
        fprintf(stderr,"Bind Error:%s\n",strerror(errno));
        exit(1);
    }
    printf("udp server start ......\n");
    udps_respon(sockfd); //进行读写操作
    close(sockfd);
}
 

client.c

   

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>

#define SERVER_PORT 8888
#define MAX_BUF_SIZE 65508

void udpc_requ(int sockfd,const struct sockaddr_in *addr,int len)
{
    char buffer[MAX_BUF_SIZE+1];
    int n;
    int i = 0;
    //while(1){
        /*从键盘读入,写到服务器*/
        printf("Please input char:\n");
        memset(buffer,0,sizeof(buffer));
        //fgets(buffer,MAX_BUF_SIZE,stdin);
        for(i = 0; i<MAX_BUF_SIZE; i ++)
        {
            buffer[i]='a';
        }
        n = sendto(sockfd,buffer,strlen(buffer),0,(struct sockaddr*)addr,len);
        //bzero(buffer,MAX_BUF_SIZE);
        printf("send bytes:%d\n",n);
    //}
}

int main(int argc,char *argv[])
{
    int sockfd;
    struct sockaddr_in addr;
    
    if(argc != 2){
        fprintf(stderr,"Usage:%s server_ip\n",argv[0]);
        exit(1);
    }
    
    /*建立sockfd描述符*/
    sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd < 0){
        fprintf(stderr,"Socket Error:%s\n",strerror(errno));
        exit(1);
    }

    /*填充服务端的资料*/
    bzero(&addr,sizeof(struct sockaddr_in));  //初始化,置0
    addr.sin_family = AF_INET;
    addr.sin_port = htons(SERVER_PORT);
    if(inet_aton(argv[1],&addr.sin_addr) < 0){  /*inet_aton函数用于把字符串型的IP地址转化成网络类型IP地址*/
        fprintf(stderr,"Ip Error:%s\n",strerror(errno));
        exit(1);
    }
    
    udpc_requ(sockfd,&addr,sizeof(struct sockaddr_in));   //进行读写操作
    close(sockfd);
}
 

MTU值

    参考TCP/IP详解卷一,做的全球互联网实验

     作为一个实验,我们多次运行修改以后的traceroute程序,目的端为世界各地的主机,可以到达15个国家(包括南极洲),使用了多个跨大西洋和跨太平洋的链路。但是,在这样做之前,作者所在子网与路由器netb之间的拨号SLIP链路MTU增加到1500与以太网相同。

    在18次运行当中,只有其中2次发现的路径MTU小于1500。其中一个跨大西洋的链路MTU值为572,而路由器返回的的是新格式的ICMP差错报文。另外一条链路,在日本的两个路由器之间,不能处理1500字节的数据帧,并且路由器没有返回新格式的ICMP差错报文。把MTU值设成1006则可以正常工作。

      从这个实验可以读出结论,现在许多但不是所有的广域网都可以处理大于512自己的分组,利用路径MTU发现机制,应用程序就可以充分利用更大的MTU来发送报文。

     对于MTU值,要求主机必须能够接收至少576字节的IP数据报。在许多UDP应用程序设计中,其应用程序数据被限制成512字节或更小,因此比这个限制值小。当然,我们可以通过分析很多路由协议(DNS TFTP BOOTP SNMP)总是发送每份小于512字节的数据。

   

 

 

         

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值