不可靠的通信协议
UDP有如下特征:
无连接:通信双方不需要事先连接
无确认:收到数据不给对方发回执确认
不保证有序、丢失不重发
采用帧同步的数据报通信方式(即通信双方每次的收
发数据量相等)
UDP适用情况
发送小尺寸数据(如:对DNS服务器进行IP地址查
询时)
在接收到数据,给出应答较困难的网络中使用
UDP。(如:无线网络)
广播、组播模式
即时通讯软件的点对点文本通讯以及音视频通讯
流媒体、VOD、VoIP、IPTV等网络多媒体服务中
的实时数据传输
UDP单播设计
发送端
1创建套接字
socket(AF_INET, SOCK_DGRAM, 0); 第二个参数SOCK_DGRAM不能搞错天成TCP的那个参数
2发送数据
ssize_t sendto(int sockfd, //UDP 通信对象 socket
const void *buf,//数据缓存 地址 size_t len, //数据大小 int flags, //属性默认为 0 即可
const struct sockaddr *dest_addr, //目标地址 (接收信息主机的地址)
socklen_t addrlen);//地址 长度 返回值: 成功 发送的字节数 失败 -1
接收端
1.创建UDP 通信socket
socket(AF_INET, SOCK_DGRAM, 0); 第二个参数SOCK_DGRAM不能搞错天成TCP的那个参数
2.绑定接收端的地址信息
bind(udp_socket,(struct sockaddr *)&server_addr,sizeof(server_addr));
3接收数据
recvfrom(udp_socket,buf,1024,0,NULL,NULL);//(只接收数据不保留地址信息)
除了在recvfrom函数中直接保留地址信息外也可以用getpeername(sockfd, (struct sockaddr *)&sa, &len)函数,根据套接字描述符获取其IP信息)
UDP组播设计
组播的特点: 加入小组的成员都可以接收到数据, 相
等于QQ群聊
1创建通信对象
socket(AF_INET, SOCK_DGRAM, 0);
2绑定UDP对象
bind
3加入组播
struct ip_mreq a;//组播结构体
a.imr_interface.s_addr = INADDR_ANY; //本地所有 网卡地址加入组播
或者
a.imr_multiaddr.s_addr = inet_addr(XXX.XXX.XXX); //指定多播地址(跟上面的地址不一样)这里要用要用D类地址
setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &a, sizeof(a));
D类地址用:于多点广播(Multicast),D类IP地址第一个字节以“1110”开始,它是一个专门保留的地址。它并不指向特定的网络,目前这一类地址被用在多点广播中。多点广播地址用来一次寻址一组计算机,它标识共享同一协议的一组计算机。(224-255).xxx.xxx
//组播结构体
struct in_addr
{
in_addr_t s_addr;
};
struct ip_mreq
{
struct in_addr imr_interface; /* 需要加入组 播的IP地址 */
struct in_addr imr_multiaddr; /* 组播地址 (D类地址) */
};
4向组播发送数据
struct sockaddr_in arry_addr;
arry_addr.sin_family=AF_INET;
arry_addr.sin_port=htons(8888); //接收信息的端口号
arry_addr.sin_addr.s_addr=inet_addr("224.x.x.x"); //所有网卡地址 sendto(udp_socket,buf,strlen(buf),0,(struct sockaddr*)&arry_addr,sizeof(arry_addr));
1.加入组播并开启组播功能 2.端口号必须要一致(端口一直才能接收到信息) 3.往组播地址中发送数据
UDP广播
UDP广播特点:在同一个(网络地址)网段中的所有主机都可以接收到数据。
每一个网络地址(网段)中的最后一个IP地址,作为该网段的广播地址!
1创建套接字
socket();
2开启广播功能
int on=1; //开启
int ret = setsockopt(udp_socket,SOL_SOCKET,SO_BROADC AST,&on,sizeof(on));
if(ret < 0) {
perror("广播开启失败:"); return -1; }
else {
printf("广播开启成功\n");
}
struct sockaddr_in dest_addr;
dest_addr.sin_family=AF_INET; //设置网络 协议 dest_addr.sin_port=htons(6666); //所有处 于192.168.64网段且,端口为 6666 的进程都可以收到 数据
dest_addr.sin_addr.s_addr=inet_addr("192.1 68.64.255"); //设置广播地址
3往广播地址发送信息
sendto(udp_socket,"hello",5,0, (struct sockaddr *)&dest_addr,sizeof(dest_addr));