组播:发送的信息,小组内所有成员都能同时接受到。
组播发送端跟接收端的具体流程为:
发送方:
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[n] = 0;
printf("peer:%s \n", recmsg);
}
完整代码如下:
发送方:
#include
#include
#include
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
#include
#include
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[n] = 0;
printf("peer:%s \n", recmsg);
}
}
}
另:如果使用多线程进行接受发送,接收时的recvfrom函数中地址不能使用group的地址进行接受,应当另随便写一个。