UDP的通信搭建流程:
因为UDP没有分服务器或者是客户端,所以最好两个端都绑定一下
-----------------------UDP单播的搭建步骤------------------------
1.创建通信socket
int udpfd=socket(AF_INET,SOCK_DGRAM,0);
if(udpfd < 0)
{
perror("creat udp fail\n");
return -1;
}
2.绑定 bind
3.数据的交互
//数据的发送
ssize_t sendto(int sockfd, //文件描述符
const void *buf, //数据的缓存区
size_t len, //数据大小
int flags,//发送与接收的属性 默认:0
const struct sockaddr *dest_addr,//接收者的IP与端口号信息
socklen_t addrlen);//信息结构体的大小
//数据的接收
ssize_t recvfrom(int sockfd, //UDP 通信描述符
void *buf,//接收后的数据缓存区
size_t len,//接收的数据大小
int flags,//默认为 0 即可
struct sockaddr *src_addr, //目标的IP地址信息
socklen_t *addrlen); //成功接收对方的IP地址信息的大小
4.关闭通信
----------------------------UDP的组播通信-------------------------------------
什么组播??
加入到一个组别里面,当我们发送数据到该组别中,所有进入该组的,UDPsocket 都可以接收到信息。
设置组播的组别的时候需要用到组播地址:
组播报文的目的地址使用D类IP地址
D 类 224.0.0.0 到 239.255.255.255 -》 该地址段的IP 是用来做组播地址的
UDP的组播设置:
1.创建通信UDP socket
2.设置该udp socket 加入到一个组播地址中 (setsockopt 设置网络通信对象的属性)
组播的设置:
setsockopt 的选项:
LEV 属性
IPPROTO_IP IP_ADD_MEMBERSHIP · 加入多播组 ip_mreq{}
*************************
struct ip_mreq zu={0};
zu.imr_multiaddr.s_addr = inet_addr("224.10.10.2"); //设置组播地址
zu.imr_interface.s_addr = inet_addr("0.0.0.0"); //让系统自己检测IP
int ret = setsockopt(socketfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&zu,sizeof(zu));
*************************
//组播地址结构体
struct ip_mreq
{
struct in_addr imr_multiaddr; //组播的IP地址
struct in_addr imr_interface; //自己的本地IP地址
};
/* Internet address. */
struct in_addr {
__be32 s_addr;
};
__be32 -》32位的整形数据
3.绑定自己的IP地址与端口号
4.接收组播数据
5.关闭通信
-------------------------------UDP的广播设置------------------------------
通过ifcofig查看当前网络的广播地址
inet 192.168.13.4 netmask 255.255.255.0 broadcast 192.168.13.255
(IP地址) (子网掩码) (当前网段的广播地址)
使用广播模式需要注意:不要经常发送广播数据,会造成网络风暴,让网络瘫痪。
1.创建UDP 的通信对象
2.开启广播功能 (setsockopt 设置广播属性)
属性设置如下:
LEV 属性
SOL_SOCKET SO_BROADCAST · · 允许发送广播数据报 · int
设置如下:
int on=1; //开启
setsockopt(socketfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));
注意: on = 1开启
on = 0关闭
3.设置该网段的广播地址并发送sendto 例如:192.168.13.XXX 广播地址为:192.168.13.255
struct sockaddr_in addr;
addr.sin_addr.s_addr = inet_addr("192.168.13.255");
4.关闭通信
注意事项:广播与组播的接收端的IP地址绑定的时候都需要填写为 “0.0.0.0” 否则会无法接收到数据!!!
//single_send.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
const int port = 12580;
const char *ip = "10.8.6.90"
int main()
{
//create socket
int st = socket(AF_INET, SOCK_DGRAM, 0);
if (st == -1)
{
printf("create socket failed ! error message :%s\n", strerror(errno));
return -1;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
//设置结构sockaddr_in类型是TCP/IP
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip);
char buf[1024] = { 0 };
while (1)
{
//read
read(STDIN_FILENO, buf, sizeof(buf));
if (sendto(st, buf, strlen(buf), 0, (struct sockaddr *) &addr,
sizeof(addr)) == -1)
{
printf("sendto failed ! error message :%s\n", strerror(errno));
break;
}
memset(buf,0,sizeof(buf));
}
close(st);
return 0;
}
//single_recv.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
const int port = 12580;
int main()
{
int st=socket(AF_INET,SOCK_DGRAM,0);
if(st==-1)
{
printf("open socket failed ! error message : %s\n",strerror(errno));
return -1;
}
int port=atoi(port);
//defien ip address strcut
struct sockaddr_in addr;
//define addr type
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
//bind port
if(bind(st,(struct sockaddr *)&addr,sizeof(addr))==-1)
{
printf("bind IP failed ! error message : %s\n",strerror(errno));
goto END;
}
char buf[1024]={0};
struct sockaddr_in client_addr;
socklen_t addrlen=sizeof(client_addr);
while(1)
{
memset(&client_addr,0,sizeof(client_addr));
if(recvfrom(st,buf,sizeof(buf),0,(struct sockaddr *)&client_addr,&addrlen)==-1)
{
printf("recvfrom failed ! error message : %s\n",strerror(errno));
goto END;
}else
{
printf("from %s:%s\n",inet_ntoa(client_addr.sin_addr),buf);
}
memset(buf,0,sizeof(buf));
}
END:close(st);
return 0;
}
//group_send.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int arg, char * args[])
{
//1.创建UDP socket
int st = socket(AF_INET, SOCK_DGRAM, 0);
if (st == -1)
{
printf("create socket failed ! error message :%s\n", strerror(errno));
return -1;
}
//设置组播IP地址
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
//设置结构sockaddr_in类型是TCP/IP
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
addr.sin_addr.s_addr = inet_addr("224.10.10.2"); //设置为组播地址
char buf[1024] = {0};
while (1)
{
//发送数据到组播地址中
scanf("%s",buf);
sendto(st, buf, strlen(buf), 0, (struct sockaddr *)&addr,sizeof(addr));
memset(buf,0,sizeof(buf));
}
close(st);
return 0;
}
//group_recv.c
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
int main(int argc,char *argv[])
{
// 1.创建udp通信socket
int socketfd = socket(AF_INET,SOCK_DGRAM,0);
if(socketfd < 0 )
{
perror("creat socket fail\n");
return -1;
}
//3.加入组播
struct ip_mreq zu={0};
zu.imr_multiaddr.s_addr = inet_addr("224.10.10.2"); //设置组播地址
zu.imr_interface.s_addr = inet_addr("0.0.0.0"); //让系统自己检测IP
int ret = setsockopt(socketfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&zu,sizeof(zu));
if(ret < 0)
{
perror("setsockopt fail\n");
return -1;
}
//2.设置UDP的地址并绑定
struct sockaddr_in seraddr={0};
seraddr.sin_family = AF_INET; //使用IPv4协议
seraddr.sin_port = htons(8888); //网络通信都使用大端格式
seraddr.sin_addr.s_addr = inet_addr("0.0.0.0");
ret = bind(socketfd,(struct sockaddr*)&seraddr,sizeof(seraddr));
if(ret < 0)
{
perror("bind fail:");
return -1;
}
//接收客户发送过来的数据
while(1)
{
char buf[1024]={0};
struct sockaddr_in src_addr={0}; //定义一个缓冲区 存放对方的IP地址信息
int len = sizeof (struct sockaddr_in);
recvfrom(socketfd,buf,1024,0,(struct sockaddr *)&src_addr,&len);
printf("buf=%s\n",buf);
}
close(socketfd);
return -1;
}
//UDP 发送广播信息
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
//1.创建UDP socket
int st = socket(AF_INET, SOCK_DGRAM, 0);
if (st == -1)
{
printf("create socket failed ! error message :%s\n", strerror(errno));
return -1;
}
//2.开启发送广播数据功能
int on=1; //开启
int ret = setsockopt(st,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on));
if(ret < 0)
{
perror("setsockopt fail\n");
return -1;
}
//3.设置该网段的广播地址
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(8888);
addr.sin_addr.s_addr = inet_addr("10.8.6.255"); //设置为广播地址
//4.发送广播数据
while(1)
{
sendto(st,"hello", strlen("hello"), 0, (struct sockaddr *)&addr,sizeof(addr));
sleep(1);
}
//5.关闭网络通信
close(st);
}