linux udp单播、组播以及广播通信

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);
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值