UDP可看作是信件邮寄,邮寄过程可能会信件丢失,是一种不可靠的数据传输服务。
但UDP性能更高,实现更加简洁。流控制是区分UDP和TCP的最重要标志。
IP的作用就是让离开主机B的UDP数据包传递给主机B,UDP根据端口号将传到主机的数据包交付给最终的UDP套接字。
UDP的高效使用
对于网络实时传输视频或音频媒体数据而言丢失一部分数据没有问题,因为需要实时服务,速度就很重要。TCP比UDP慢主要由于
- 收发数据前后进行的连接设置及清楚过程
- 收发数据过程中为保证可靠性而添加的流控制
实现基于UDP的服务器端/客户端
UDP服务器端/客户端不需在连接状态下交换数据,无需连接过程,不必调用listen和accept函数。
UDP服务器端/客户端均只需一个套接字。
TCP套接字是一一对应的,若向10个客户端提供服务,除了守门的服务器套接字外还需10个服务器端套接字。UDP只需一个邮筒。
基于UDP的数据I/O函数
创建好TCP套接字后,传输数据时无需再添加地址信息,因为套接字间将保持连接,即TCP套接字知道目标地址信息。但UDP不会保持连接,因此每次传输数据都要添加目标地址信息。
#include<sys/socket.h>
ssize_t sendto(int sock,void *buff,size_t nbytes,int flags,struct sockaddr *to, socklen_t addrlen);
- sock用于传输数据的UDP套接字文件描述符。
- buff保存待传输数据的缓冲地址值。
- nbytes待传输的数据长度,以字节为单位。
- flags可选项参数,若没有则传递0。
- to存有目标地址信息的sockaddr结构体变量的地址值。
- addrlen传递给参数to的地址值结构体变量长度。
接收UDP数据函数
#include<sys/socket.h>
ssize_t recvfrom(int sock,void *buff,size_t nbytes,int flags,struct sockaddr *from, socklen_t addrlen);
- sock用于传输数据的UDP套接字文件描述符。
- buff保存待传输数据的缓冲地址值。
- nbytes待传输的数据长度,以字节为单位。
- flags可选项参数,若没有则传递0。
- from存有发送端地址信息的sockaddr结构体变量的地址值。
- addrlen传递给参数to的地址值结构体变量长度。
注意:UDP不同于TCP,不存在请求连接和受理过程,无法明确服务器端和客户端。
UDP客户端套接字的地址分配
UDP调用sendto函数时自动分配IP和端口号。
UDP的数据传输特性和调用connect函数
存在数据边界的UDP套接字
UDP是具有数据边界的协议,传输中调用I0函数的次数非常重要。因此,输入函数的调用次数应和输出函数的调用次数完全一致,这样才能保证接收全部已发送数据。例如,调用3次输出函数发送的数据必须通过调用3次输人函数才能接收完。
已连接UDP套接字与未连接UDP套接字
TCP套接字中需注册待传输数据的目标IP和端口号,而UDP则无需注册。通过sendto函数传输数据的3个阶段。
- 向UDP套接字注册目标IP和端口号。
- 传输数据。
- 删除UDP套接字中注册的目标地址信息。
未注册目标地址信息的套接字称为未连接套接字,注册了目标地址的套接字称为连接connected套接字。将UDP套接字变成已连接套接字会提高效率。
创建已连接UDP套接字的过程格外简单,只需针对UDP套接字调用connect函数,这不意味着要与对方UDP套接字连接,只是向UDP套接字注册目标IP和端口信息。
Sock=Socket(PF INET,SOCK DGRAM,0);
memset(&adr,0,sizeof(adr));
adr.sin family=AF INET;
adr.sin addr.saddr=.
adr.sin port=
connect(sock,(structsockaddr*)&adr,sizeof(adr));