如果UDP数据包超过MTU,它能被分割成几个更小的数据包吗?看起来MTU碎片是关于IP层的,所以我认为它可以。
如果是,为避免碎片,建议通过UDP发送的最大数据包大小是多少?为什么?
如果您想要特定大小的数据包碎片,下面的示例将非常有用。
#define UDP_FRAG_1024 1024
static int udp_raw_socket = -1;
static int udp_ip_iden = 1234;
int udp_frag1024_sendto(int s, caddr_t buf, int buf_len, int flags, struct sockaddr *to, int to_len)
{
/* You must be in the sudoers files. */
struct sockaddr_in sin;
struct sockaddr_in *ptr_din = (struct sockaddr_in *)to;
int sin_len = sizeof(sin);
unsigned char packet[1500];
short packet_len;
short ip_iden;
int sent1;
int sent2;
if (udp_raw_socket == -1) {
int opt_val = 1;
int *ptr_opt_val = &opt_val;
udp_raw_socket = socket(AF_INET,SOCK_RAW,IPPROTO_RAW);
(void)setsockopt(udp_raw_socket,IPPROTO_IP,IP_HDRINCL,(char *)ptr_opt_val,sizeof(opt_val));
}
if (buf_len > 2*UDP_FRAG_1024) {
printf("buf_len %d not supported.\n",buf_len);
return -1;
}
else if (buf_len <= UDP_FRAG_1024) {
return sendto( s, buf, buf_len, flags, to, to_len );
}
else {
ip_iden = udp_ip_iden++;
(void)getsockname(s,(struct sockaddr *)&sin,&sin_len);
/* 1st framentation - IP header */
packet_len = 20 + 8 + UDP_FRAG_1024;
packet[0] = 0x45; /* ver and header length */
packet[1] = 0x00; /* tos */
*(short *)&packet[2] = htons(packet_len);
*(short *)&packet[4] = htons(ip_iden);
packet[6] = 0x20; packet[7] = 0x00; /* flag */
packet[8] = 0x40; /* ttl */
packet[9] = 0x11; /* udp */
packet[10] = 0x00; packet[11] = 0x00;/* checksum */
memcpy( &packet[12], &sin.sin_addr.s_addr, 4 );
memcpy( &packet[16], &ptr_din->sin_addr.s_addr, 4 );
/* 1st framentation - UDP header */
memcpy( &packet[20], &sin.sin_port, 2 );
memcpy( &packet[22], &ptr_din->sin_port, 2 );
*(short *)&packet[24] = htons(8+buf_len);
packet[26] = 0x00; packet[27] = 0x00; /* checksum */
/* 1st framentation - payload */
memcpy( &packet[28], buf, UDP_FRAG_1024 );
sent1 = sendto(udp_raw_socket,packet,packet_len,0,to,sizeof(struct sockaddr_in));
/* 2nd framentation */
packet_len = 20 + buf_len - UDP_FRAG_1024;
*(short *)&packet[2] = htons(packet_len);
packet[6] = 0x00; packet[7] = (8+UDP_FRAG_1024)/8; /* flag:0x81*8=129*8=1032=8+1024 */
packet[10] = 0x00; packet[11] = 0x00; /* checksum */
memcpy( &packet[20], buf+UDP_FRAG_1024, buf_len-UDP_FRAG_1024 );
sent2 = sendto(udp_raw_socket,packet,packet_len,0,to,sizeof(struct sockaddr_in));
}
return ((sent1 - 20 - 8) + (sent2 - 20));
}
void udp_frag1024_sendto_test()
{
int s;
struct sockaddr_in my_addr;
struct sockaddr_in to_addr;
char buffer[4096];
int sent;
s = socket(AF_INET, SOCK_DGRAM, 0);
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = inet_addr("192.168.0.229");
my_addr.sin_port = htons(12345);
bind(s,(struct sockaddr *)&my_addr,sizeof(my_addr));
to_addr.sin_family = AF_INET;
to_addr.sin_addr.s_addr = inet_addr("192.168.0.19");
to_addr.sin_port = htons(12345);
memset(buffer,'A',sizeof(buffer));
sent = udp_frag1024_sendto(s,buffer,2047,0,(struct sockaddr *)&to_addr,sizeof(struct sockaddr_in));
close(s);
printf("sent %d bytes\n",sent);
}
如果任何IP数据报大于MTU,则可以将其分段。它是否包含UDP、TCP、ICMP等并不重要。
大多数以太网支持1500字节的MTU。IPv4报头为20字节,UDP报头为8字节,UDP数据包的有效负载不应大于1500-20-8=1472字节,以避免碎片。
这是假设数据包中不存在IP选项。如果是这样的话,有效载荷将需要小于该值才能解释它。
这仅适用于IPv4。IPv6不支持分段。
您还可以看到关于UDP的MTU的问题。
我一直在写一个程序,它使用UDP上的停止和等待协议通过局域网和广域网发送数据包。我最近一直在测试我的程序,并注意到较大的数据包(接近64k字节)的丢包率更高。直觉上这是有道理的,但实际原因是什么?
我创建了某种类型的客户机/服务器应用程序,它有自己的数据ACK系统。由于某些限制,它最初是用TCP编写的,但它的基础是考虑到UDP编写的。 我发送到服务器的数据包有自己的封装(数据包id和数据包大小报头。我知道UDP还有一个校验和,所以我没有为此添加报头),但是TCP是如何工作的,我知道服务器可能接收不到整个数据包,所以我收集并缓冲了接收到的数据,直到收到一个完整的有效数据包。 我想知道的是:如果
根据Stevens(图示为TCP/IP),traceroute程序用增量TTL(1、2、3等)向目的主机发送UDP数据包,以从ICMP TTL过期消息中获取中间跳信息。 “到达目的地”条件是ICMP端口无法到达的消息,因为traceroute寻址的随机端口数量很高(也就是说,不太可能有人在那里监听) 所以我的问题是:是否有技术原因(缺点、RFCs等)使用UDP数据包而不使用例如ICMP回送请求消息
通过UDP发送大量的小数据包会占用更多的资源(cpu、zlib压缩等)。我在这里读到,通过UDP发送一个大的~65kBYTEs数据包可能会失败,所以我认为发送许多较小的数据包会更频繁地成功,但是随之而来的是使用更多处理能力的计算开销(或者至少这是我假设的)。问题基本上是这样的:发送最大成功数据包并将计算保持在最低限度的最佳方案是什么?有没有一个特定的尺寸在大部分时间都有效?我使用Erlang作为服
好的,我正在为我的网络课程编程,我必须使用UDP在Java中实现一个项目。我们正在实现一个HTTP服务器和客户端以及一个“gremlin”函数,该函数以指定的概率破坏数据包。HTTP服务器必须在应用层将一个大文件分成多个段,然后通过UDP发送到客户端。客户端必须在应用层重新组装接收到的段。然而,我想知道的是,如果UDP根据定义是不可靠的,为什么我必须在这里模拟不可靠? 我的第一个想法是,也许这仅仅
我正在使用在我的客户端应用程序中执行以及 最大数据包大小限制也存在于中,即?但是我可以使用中的发送大于最大数据包大小的数据块 这是怎么运作的?这是因为是基于流的,负责在较低层创建数据包吗?有什么方法可以增加UDP中的最大数据包大小吗? 当我在客户端读取时,我从服务器端发送的UDP数据包的一些字节是否可能丢失?如果是,那么有没有办法只检测UDP客户端的损失?