UDP属于运输层的协议,特点是不可靠、无连接。UDP除了复用/分解功能及少量的差错检测外,几乎没有额外的功能,所以使用UDP编写应用程序相当于和IP层打交道。
UDP协议格式
UDP协议格式很简单,只提供了64bit(8字节),其结构如下:
从图中可以看出,UDP头部只有4个字段,每个字段是2个字节。而且四个字段都比较容易理解。值得说明的是,长度字段指明了包括首部在内的UDP报文段长度(以字节为单位)。比如说,在应用层发送的数据为100字节,那么,在UDP报文中,长度字段应该是108(100+8个字节的首部)。 UDP检验和提供了差错检测的功能。因为UDP需要保证传输的数据是正确的,因为在传送过程中某条链路可能没有使用差错检测协议,这个时候如果数据发送错误,就会出现问题。所以UDP就必须在端到端的的基础上在运输层提供差错检测。
UDP检验和原理是发送方的所有16比特字的和进行反码计算,求和遇到的任何溢出都回卷。然后将得到的结果放在UDP报文段中的检验和字段。首先通过一个例子来说明,假定有以下3个16bit的字:
0110 0110 0110 0000 0101 0101 0101 0101 1000 1111 0000 1100
这些16比特字前两个之和是:
0110 0110 0110 0000
0101 0101 0101 0101
1011 1011 1011 0101
再将上面的和与第三个字相加,得出
1011 1011 1011 0101
1000 1111 0000 1100
0100 1010 1100 0010
注意最后一次加法有溢出,它要被回卷。反码运算就是将所有的0换成1,所有的1换成0。因此,该和0100 1010 1100 0010的反码结果就是1011 0101 0011 1101, 这就变为了校验和。
差错检测实践
现在通过一个UDP详细的报文看一下,这里我写了一个简单的UDP程序,然后发送客户端连接,发送一个hello发送给服务端。通过wireshark抓取了这个报文进行分析。
通过抓包可以得到以下数据
然后通过校验程序验证,代码如下
#include<stdio.h>
unsigned short checksum(unsigned short *buf,int nword)
{
unsigned long sum;
for(sum=0;nword>0;nword--)
{
sum += *buf++;
sum = (sum>>16) + (sum&0xffff);
}
return ~sum;
}
void main()
{
unsigned short buffer[20]={0x0aaa,0x3bbf,0xd20e,0x960d,0x0011,0x001c,0xd123,0x2742,0x001c,0x0000,0x6c41,0x5661,0x0000,0x0e00,0xf8b6,0xd401,0x9313,0x0000,0x0000,0x0000};
int n=20;
unsigned short re_checksum;
re_checksum=checksum(buffer,n);
printf("%x\t",re_checksum);
if(re_checksum==0x285c)
printf("校验和正确!\n");
else
printf("校验和不正确!\n");
}
验证输出为73c0。结果与Checksum字段一致。
值得注意的是在计算Checksum时,需要在UDP首部再加上一个伪首部,其实就是IP头部的
源IP, 目的IP, UDP报文长度,UDP协议(十进制为17), 一共12个字节。
所以整体计算公式就是, 伪首部加上UDP首部:
src ip + des ip + udp length + upd protocol + src port + des port + check sum + udp length + data length
加完之后,然后如果有溢出进行翻转,最后再取反就行了。
基于python实现
UDP服务端
客户端
通过示例可以看出,由于UDP是无连接的协议,所以编码也很简单,服务端绑定IP地址,然后就可以接收数据了。客户端发送数据的时候也是直接指定IP地址和端口号,调用sendto函数就可以了。
根据示例,可以知道UDP的连接是不保存的。所以每次发送数据都会重新创建一个连接, 然后发送数据。整体流程如下: 1、向UDP套接字注册目标IP和端口号; 2、传输数据; 3、删除UDP套接字中注册的目标地址信息。 基本上每次发送数据都会重复以上三个步骤。 通过connect函数可以让UDP连接上服务端之后,保持连接不断,可以优化性能。
UDP使用场景
UDP虽然是一种不可靠的连接,但是其给应用层提供了很大的扩展性。所以对于一些视频软件可以使用UDP,包括现在google推行的QUIC协议也是基于UDP的。
参考文章:
blog.csdn.net/stone_Yu/ar…
www.faqs.org/rfcs/rfc107…
www.cs.binghamton.edu/~steflik/cs…
《计算机网络--自顶向下》第6版