linux 下c语言同一组播地址udp通讯

欢迎使用Markdown编辑器写博客

UDP组播通讯可用
功能:
实现两台设备通过同一组播地址进行信息交互.
机器A 机器B
机器A发送指令,机器B接收指令 机器B回复一条报文 机器A 接收一条报文
机器A为发送方,客户端
机器B为接收端服务器端

发送端
Bind本地端口与IP,向组里发送数据,从本地接收数据。记得setsockopt加组与reuseaddr
机器B代码:
/*
*本功能只能实现一对一的组播通讯,
*若要实现一对多通讯,需对发送代码进行简单修改
*本人已经试过一对多的,至于一对几可以根据心跳包个数,即几个人像里面
*发送心跳包,更改很简单,就不详细说了
*
*
*
*/
/代码块/


    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    #include 
     
    #define BUFLEN 255
    ```
    
        static int count = 0;
        static struct itimerval oldtv;
        
        void set_timer(int sec, int usec)
        {
        	struct itimerval itv;
        	itv.it_interval.tv_sec = sec;
        	itv.it_interval.tv_usec = usec;
        	itv.it_value.tv_sec = sec;
        	itv.it_value.tv_usec = usec;
        	setitimer(ITIMER_REAL, &itv, &oldtv);
        }
        
        void signal_handler(int m)
        {
        	count++;
        	//printf("%d\n", count);
        }
        
        int main(int argc, char **argv)
        {
        		struct sockaddr_in peeraddr, myaddr;
        	 	printf("in main\n");
        		int sockfd;
        		char recmsg[BUFLEN + 1];
        		unsigned int socklen;
        	 	signal(SIGALRM, signal_handler);
        		set_timer(3,0);
    
    	/* 创建 socket 用于UDP通讯 */
    	sockfd = socket(AF_INET, SOCK_DGRAM,0);
    	if (sockfd < 0) {
    		printf("socket creating error\n");
    		exit(1);
    	}
    	socklen = sizeof(struct sockaddr_in);
     
    	/* 设置对方的端口和IP信息 */
    	memset(&peeraddr, 0, socklen);
    	peeraddr.sin_family = AF_INET;
    	peeraddr.sin_port = htons(8888);
    	peeraddr.sin_addr.s_addr=inet_addr("224.1.1.12");	
    
    	int iOptionValue = 1;
    	struct ip_mreq mreq;
    	mreq.imr_multiaddr.s_addr=inet_addr("224.1.1.12");//组播地址
    	mreq.imr_interface.s_addr=inet_addr("192.168.142.128");//发送端mreq的interface为本地地址
     
    	/* 设置自己的端口和IP信息 */
    	memset(&myaddr, 0, socklen);
    	myaddr.sin_family = AF_INET;
    	myaddr.sin_port = htons(8686);
    	myaddr.sin_addr.s_addr = inet_addr("192.168.142.128");
    	
    	int opt=1;
     			
    	int yes = 1; 
    
    	if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &yes, sizeof(yes)) < 0)
    	{
    		//close(m_socket);
    		perror("setsockopt");
    		//return -2;
    	}
    	
    	//参数loop设置为0禁止回送,设置为1允许回送
    	int Loop = 1;
    	//if (! LoopBack) Loop = 0;	
    	if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&Loop, sizeof(int)) < 0)
    	{
    		perror("setsockopt:IP_MULTICAST_LOOP");
    		//return -4;
    	}
    
        //将socket
        	if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) == -1)
        	 {  
               		 perror("setsockopt");  
               		 exit(-1);  
           	 }
    	
    	/* 绑定自己的端口和IP信息到socket上 */
    	if (bind(sockfd, (struct sockaddr *) &myaddr,sizeof(struct sockaddr_in)) == -1) 
    	{
    		perror("Bind error\n");
    		exit(0);
    	}
    
     	char buf[128]={0};
    	/* 循环接受用户输入的消息发送组播消息 */	
    	int k=0;
    	for (;;) 
    	{
    		/* 接受用户输入 */
    
    			printf("请输入:\n");
    			bzero(recmsg, BUFLEN + 1);
    		
    			if (fgets(recmsg, BUFLEN, stdin) == (char *) EOF)
    				exit(0);
    
    		/* 发送消息 */
    			if (sendto(sockfd,recmsg, sizeof(recmsg), 0,(struct sockaddr *) &peeraddr, sizeof(struct sockaddr_in)) < 0) 
    			{
    				printf("sendto error!\n");
    			}
    			else
    			{
    				int t=0;
    				printf("begin recv\n");
    				int n = recvfrom(sockfd, buf,sizeof(buf), 0,  
                    		(struct sockaddr *) &myaddr, &socklen);  //
    				if(n>0)
    				{
    					printf("发送端接收成功recv ok buf is %s\n",buf);
    					count=0;		
    				}
    
    	#include "g_recv.h" 
    	int main(int argc, char **argv)  
         {  	
        	int k=udp_group_recv("224.1.1.12",8888);
          
        }  

机器A的代码:

 #include "g_recv.h"
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    #include 
    #define BUFLEN 255

int n1=0;
static int count = 0;
static struct itimerval oldtv;

void set_timer(int sec, int usec)
{
		struct itimerval itv;
		itv.it_interval.tv_sec = sec;
		itv.it_interval.tv_usec = usec;
		itv.it_value.tv_sec = sec;
		itv.it_value.tv_usec = usec;
		setitimer(ITIMER_REAL, &itv, &oldtv);
}

void signal_handler(int m)
{
	count ++;
	if(n1>=1 && count>2)
	{
		//system("cd /root/Desktop/group; ./send");
		
	}
	//printf("%d\n", count);
}

```

    int udp_group_recv(char *group_ip,int group_port)
    {
     /* 设置发送组播消息的源主机的地址信息 */  
     	struct sockaddr_in peeraddr,myaddr;  
     	struct in_addr ia;  
    	int sockfd;
     	char recv[300];
      	unsigned int socklen,n;
       	struct hostent *group;
     	struct ip_mreq mreq; 
    	signal(SIGALRM, signal_handler);
    	set_timer(2,0);
    	socklen=sizeof(struct sockaddr_in);
    	sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
    	memset(&peeraddr,0, socklen);  
    //组播地址设置
      	peeraddr.sin_family = AF_INET;   
       	peeraddr.sin_addr.s_addr=inet_addr(group_ip);	
        peeraddr.sin_port = htons(group_port);  
        /* 设置发送组播消息的源主机的地址信息 */  
    	mreq.imr_multiaddr.s_addr=inet_addr(group_ip); 	  	
    	mreq.imr_interface.s_addr = htonl(INADDR_ANY);
	
	if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,  sizeof(struct ip_mreq)) == -1)
	{  
        	perror("setsockopt");  
        	exit(-1);  
    	}  

	//  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
	myaddr.sin_family=AF_INET;
	myaddr.sin_port=htons(8888);
	myaddr.sin_addr.s_addr=INADDR_ANY;//recv端为INADDR——ANY

	int opt=1; 
 	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {  
        perror("setsockopt REUSE");  
        exit(-1);  
        } 
	
	int yes = 1;
	/* allow multiple sockets to use the same PORT number */

	if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &yes, sizeof(yes)) < 0)
	{
		//close(m_socket);
		perror("setsockopt");
		//return -2;
	}
	int rcvbuf_len;
	socklen_t len = sizeof(rcvbuf_len);
	
	
        rcvbuf_len = 200 * 1024 * 512;//100M
	len = sizeof(rcvbuf_len);
	//int e = EBADF;
	if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUFFORCE, (void *) &rcvbuf_len, len) < 0)
	{
		perror("setsockopt");
	}
        /*

*/
	

    //参数loop设置为0禁止回送,设置为1允许回送
    	int Loop = 0;
    	//if (! LoopBack) Loop = 0;	
    	if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&Loop, sizeof(int)) < 0)
    	{
    		perror("setsockopt:IP_MULTICAST_LOOP");
    		//return -4;
    	}
       	if (bind(sockfd, (struct sockaddr *) &peeraddr, sizeof(struct sockaddr_in)) == -1) 
    	{  
            	printf("Bind error\n");  

   	
    }  
	
	char buf[128]={0};
	//pthread_create(&pd,NULL,go,);
    /* 循环接收网络上来的组播消息 */  
    	for (;;) 
	{  

		printf("n1 is %d\n",n1);
	
		n = recvfrom(sockfd, buf,sizeof(buf), 0,  (struct sockaddr *) &peeraddr, &socklen);  
       		if (n < 0)
		{  
           		 printf("recvfrom err in udptalk!\n");  
          		 exit(4);  
       		} 
	
		else 	
		{  
	
			count=0;
			n1++;
			printf("peer:%s\n", buf);  
			int k=0;
			printf("请输入:\n");
			bzero(recv, sizeof(recv));
			if (fgets(recv, sizeof(recv), stdin) == (char *) EOF)
				exit(0);
    L:			n=sendto(sockfd, recv,sizeof(recv), 0,(struct sockaddr *) &peeraddr, socklen);
    			if(n>0)
    			{
    				printf("recv 端发送成功\n");
	
			}
        }  
    }  
	return 0;
    } 

希望大家多提宝贵意见谢谢。

你可能感兴趣的:(linux 下c语言同一组播地址udp通讯)