您的位置:首页 > 理论基础 > 计算机网络

Linux 网络通信之组播

2015-12-07 14:40 585 查看
组播可以看成是单播和广播的折中。当发送组播数据包时,只有加入指定多播组的主机数据链路层才会处理,其他主机在数据链路层会直接丢掉收到的数据包。即我们可以通过组播的方式和指定的若干台主机通信。

D类地址:范围从224.0.0.1到239.255.255.254.此类地址又称为组播地址。每个组播地址代表一个多播组。

组播包的发送和接收通过UDP套接字实现。

组播包发送流程如下:

(1)创建UDP套接字;socket(AF_INET, SOCK_DGRAM, 0)

(2)指定目标地址和端口;struct sockaddr_in

(3)发送数据包;sendto( )

send.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>

#define  err_log(log) do{perror(log); exit(1);}while(0)

#define  N 128

int main(int argc, const char *argv[])
{

int sockfd;
struct sockaddr_in groupcastaddr;
char buf
= {0};

if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
err_log("fail to socket");
}

groupcastaddr.sin_family = AF_INET;
groupcastaddr.sin_addr.s_addr = inet_addr("225.0.0.3");
groupcastaddr.sin_port = htons(10000);

while(1)
{
printf("Input > ");
fgets(buf, N, stdin);
if(sendto(sockfd,buf, N, 0, (struct sockaddr *)&groupcastaddr, sizeof(groupcastaddr)) < 0)
{
err_log("fail to sendto");
}

}

return 0;
}


组播接收流程如下:

(1)创建UDP套接字;socket(AF_INET, SOCK_DGRAM, 0)

(2)加入多播组;setsockopt( )

(3)填充组播地址信息(组播IP地址和端口);struct sockaddr_in

(4)接收数据包;recvfrom( )

多播结构体:

struct ip_mreq
{
/* IP multicast address of group.  */  组播的ip地址
struct in_addr imr_multiaddr;

/* Local IP address of interface.   */  本机的ip地址
struct in_addr imr_interface;
};

mreq.imr_multiaddr.s_addr = inet_addr(“224.10.10.1”);  //组播地址
mreq.imr_interface.s_addr = htonl(INADDR_ANY);  //INADDR_ANY  0 地址 ,任意的主机地址

setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));


recv.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>

#define  err_log(log) do{perror(log); exit(1);}while(0)
#define  N  128

int main(int argc, const char *argv[])
{

int sockfd;
char buf
;
struct sockaddr_in groupcastaddr, srcaddr;
struct ip_mreq mreq;

if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
err_log("fail to socket");
}
/*为套接字绑定组播地址和端口*/
groupcastaddr.sin_family = AF_INET;
groupcastaddr.sin_addr.s_addr = inet_addr("225.0.0.3");
groupcastaddr.sin_port = htons(10000);

/*加入多播组,允许数据链路层处理指定组播包*/
mreq.imr_multiaddr.s_addr = inet_addr("225.0.0.3");
mreq.imr_interface.s_addr = htonl(INADDR_ANY);

if(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq, sizeof(mreq)) < 0)
{
err_log("fail to setsockopt");
}

int on = 1;
if(setsockopt(sockfd,SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
{
err_log("fail to setsockopt");
}

if(bind(sockfd, (struct sockaddr*)&groupcastaddr, sizeof(groupcastaddr)) < 0)
{
err_log("fail to bind");
}

socklen_t addrlen = sizeof(struct sockaddr);

while(1)
{
if(recvfrom(sockfd,buf, N, 0, (struct sockaddr *)&srcaddr, &addrlen) < 0)
{
err_log("fail to sendto");
}
printf("buf:%s ---> %s %d\n", buf, inet_ntoa(srcaddr.sin_addr), ntohs(srcaddr.sin_port));
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: