内容: 记录当UDP报文数据内容大于MTU大小的时候,其实不一定分片

UDP什么时候分片?

UDP报文中有长度的字段,是16位的,那么UDP报文的最大长度是65536字节,但是一般MTU的大小不会达到
65536字节这么大,而是一般为1500字节,那么这时候就会引起分片

UDP一定会分片吗?

答案:不一定,当UDP报文是上交本地协议栈的时候,并不会引起分片的!

原因:本地环回报文实际并不需要层层封装到链路层再物理层这个过程,也就不受MTU的影响。而是在IP层就
     直接复制到本地协议栈目的连接的接受缓冲区了。

不分片的情况:


//服务端代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
 
#define MAXBUF 70000
int main(int argc, char const *argv[])
{
	int s = 0;
	int n = 0;
	int reuse = 1;
	int cli_len = sizeof(struct sockaddr);
	int port = 5555;
	char buf[MAXBUF] = {0};
	struct sockaddr_in addr, cli;
 
	bzero(&addr, sizeof(addr));
	addr.sin_family = PF_INET;
	addr.sin_addr.s_addr = INADDR_ANY;
	addr.sin_port = htons(port);
 
	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s<0)
	{
		perror("socket");
		return -1;
	}
	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
	{
		perror("bind");
		return -1;
	}
 
	while(1){
		memset(buf, 0, MAXBUF);
		n = recvfrom(s, buf, MAXBUF, 0, (struct sockaddr *)&cli, &cli_len);
		if(n<0){
			perror("recvfrom");
			return -1;
		}else{
			printf("receive msg from %s(port=%d) len %d: %s\n",inet_ntoa(cli.sin_addr), port, n, buf);
		}
	}	
	return 0;
}

//客户端代码:
/*client.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#define MAXBUF 60000
int main(int argc, char const *argv[])
{
    int s = 0;
    int n = 0;
    int reuse = 1;
    int port = 5555;
    struct sockaddr_in srv;
    char buf[MAXBUF] = {0};

    for (int i = 0; i < 60000; i++)
    {
        buf[i] = 'k';
    }
    buf[59999] = '\0';
    /*解析参数*/
    if (argc != 2)
    {
        printf("Usage:%s ServerIP\n", argv[0]);
        return -1;
    }
 
    bzero(&srv, sizeof(srv));
    srv.sin_family = PF_INET;
    srv.sin_addr.s_addr = inet_addr(argv[1]);
    srv.sin_port = htons(port);
    /*创建 UDP 套节字*/
    s = socket(AF_INET, SOCK_DGRAM, 0);
    if(s<0){
        perror("socket");
        return -1;
    }
        /*通过套节字 s 向服务器发送数据*/
        if ((n = sendto(s, buf, strlen(buf), 0, (struct sockaddr *) &srv, sizeof(struct sockaddr))) < 0)
        {
            perror("sendto");
            return -1;
        }else{
            printf("send to %s(port=%d) len %d:%s\n", argv[1], port, n, buf);
        }
}

代码运行:
在这里插入图片描述
在这里插入图片描述
(注意:这里的ip地址为本地网卡的地址)

抓取报文:
在这里插入图片描述
报文分析:

1、报文的数据大小为59999字节,因为发送的数组是60000字节,但是最后一个字节我设置了'\0'

259999字节是大于MTU的,但是报文并没有分片,可以看到IP层的不分片标志位置1了,表示不允许分片,
   因为这个是发给本地网卡的,那么可以直接在IP层就可以处理了,不需要往下再走其它层了

3、可以看到链路层及以下的层在报文中已经没有再封装了,采用了伪协议
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐