您的位置:首页 > 运维架构 > Linux

linux下c++实现udp组播模式

2017-06-14 22:32 302 查看
组播:发送的信息,小组内所有成员都能同时接受到。

组播发送端跟接收端的具体流程为:

发送方:

a.创建socket

socket_fd=socket(AF_INET,SOCK_DGRAM,0);
if(socket_fd < 0)
{
perror("socket multicast!");
exit(1);
}


b.设置发送的群组的地址

/*set up the destination address*/
memset(&group_addr,0,sizeof(struct sockaddr_in));
group_addr.sin_family = AF_INET;
group_addr.sin_port = htons(group_port);
group_addr.sin_addr.s_addr = inet_addr("230.1.1.1");


c.发送,调用sendto()函数

if (sendto  (socket_fd, recmsg, strlen(recmsg), 0,  (struct sockaddr *) &group_addr,
sizeof(struct sockaddr_in)) < 0)
{
printf("sendto error!\n");
exit(1);
}


接收方:

1.创建socket

socket_fd=socket(AF_INET,SOCK_DGRAM,0);
if(socket_fd < 0)
{
perror("socket multicast!");
exit(1);
}


2.(可选)设置多个socket公用同一端口号,如果在同一台电脑中需要多个程序接受的话,需要设置。

/* allow multiple sockets to use the same PORT number */
if(setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0)
{
perror("Reusing ADDR failed");
exit(1);
}


3.设置本地地址信息

/*set up the local address*/
memset(&local_addr,0,sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
local_addr.sin_port = htons(group_port);              //this port must be the group port


注意:本地的端口必须为群组的端口,地址为本地地址。

4.bind本地地址

/*bind local address*/
if(bind(socket_fd,(struct sockaddr *)&local_addr,sizeof(local_addr)) == -1)
{
perror("Binding the multicast!");
exit(1);
}


5.设置群组地址与端口

/*use the setsocketopt() to request joining the multicast group*/
mreq.imr_multiaddr.s_addr=inet_addr(group_ip);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);


6.加入群组

if(setsockopt(socket_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0)
{
perror("setsockopt multicast!");
exit(1);
}


7.接受消息

bzero(recmsg, sizeof(recmsg)-1);
n = recvfrom(socket_fd, recmsg, sizeof(recmsg)-1, 0,(struct sockaddr *)&group_addr, &addr_len);
if (n < 0) {
printf("recvfrom err in udptalk!\n");
exit(4);
} else {
/* success recieve the information */
recmsg
= 0;
printf("peer:%s \n", recmsg);
}


完整代码如下:

发送方:

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <iostream>

using namespace std;

int main(void)
{
char group_ip[20];
int group_port = 7838;
int local_port = 11112;
strcpy(group_ip,"230.1.1.1");

char recmsg[256];

int n;
int socket_fd;
struct sockaddr_in group_addr; //group address
struct sockaddr_in local_addr;//local address
struct ip_mreq mreq;
socklen_t addr_len = sizeof(group_addr);
u_int yes;

socket_fd=socket(AF_INET,SOCK_DGRAM,0); if(socket_fd < 0) { perror("socket multicast!"); exit(1); }

/* allow multiple sockets to use the same PORT number */
if (setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0)
{
perror("Reusing ADDR failed");
exit(1);
}

/*set up the destination address*/ memset(&group_addr,0,sizeof(struct sockaddr_in)); group_addr.sin_family = AF_INET; group_addr.sin_port = htons(group_port); group_addr.sin_addr.s_addr = inet_addr("230.1.1.1");

/*set up the local address*/ memset(&local_addr,0,sizeof(local_addr)); local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = htonl(INADDR_ANY); local_addr.sin_port = htons(group_port); //this port must be the group port
/*bind local address*/ if(bind(socket_fd,(struct sockaddr *)&local_addr,sizeof(local_addr)) == -1) { perror("Binding the multicast!"); exit(1); }
/*use the setsocketopt() to request joining the multicast group*/ mreq.imr_multiaddr.s_addr=inet_addr(group_ip); mreq.imr_interface.s_addr=htonl(INADDR_ANY);
if (setsockopt(socket_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0)
{
perror("setsockopt multicast!");
exit(1);
}
/*loop to send or recieve*/
while(1)
{
/*send*/
bzero(recmsg, sizeof(recmsg));
if (fgets(recmsg, sizeof(recmsg), stdin) == (char *) EOF)
{
exit(0);
}
if (sendto (socket_fd, recmsg, strlen(recmsg), 0, (struct sockaddr *) &group_addr,
sizeof(struct sockaddr_in)) < 0)
{
printf("sendto error!\n");
exit(3);
}
printf("'%s' send ok\n", recmsg);

}

}


接收方:

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <iostream>

using namespace std;

int main(void)
{
char group_ip[20];
int group_port = 7838;
int local_port = 11112;
strcpy(group_ip,"230.1.1.1");

char recmsg[256];

int n;
int socket_fd;
struct sockaddr_in group_addr; //group address
struct sockaddr_in local_addr;//local address
struct ip_mreq mreq;
socklen_t addr_len = sizeof(group_addr);
u_int yes;

socket_fd=socket(AF_INET,SOCK_DGRAM,0); if(socket_fd < 0) { perror("socket multicast!"); exit(1); }

/* allow multiple sockets to use the same PORT number */
if (setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0)
{
perror("Reusing ADDR failed");
exit(1);
}

/*set up the destination address*/ memset(&group_addr,0,sizeof(struct sockaddr_in)); group_addr.sin_family = AF_INET; group_addr.sin_port = htons(group_port); group_addr.sin_addr.s_addr = inet_addr("230.1.1.1");

/*set up the local address*/ memset(&local_addr,0,sizeof(local_addr)); local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = htonl(INADDR_ANY); local_addr.sin_port = htons(group_port); //this port must be the group port
/*bind local address*/ if(bind(socket_fd,(struct sockaddr *)&local_addr,sizeof(local_addr)) == -1) { perror("Binding the multicast!"); exit(1); }
/*use the setsocketopt() to request joining the multicast group*/ mreq.imr_multiaddr.s_addr=inet_addr(group_ip); mreq.imr_interface.s_addr=htonl(INADDR_ANY);
if (setsockopt(socket_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0)
{
perror("setsockopt multicast!");
exit(1);
}
/*loop to send or recieve*/
while(1)
{

bzero(recmsg, sizeof(recmsg)-1);
n = recvfrom(socket_fd, recmsg, sizeof(recmsg)-1, 0,
(struct sockaddr *) &group_addr, &addr_len);
if (n < 0) {
printf("recvfrom err in udptalk!\n");
exit(4);
} else {
/* success recieve the information */
recmsg
= 0;
printf("peer:%s \n", recmsg);
}

}

}


另:如果使用多线程进行接受发送,接收时的recvfrom函数中地址不能使用group的地址进行接受,应当另随便写一个。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: