组播在内核里面对应的一个重要的结构体是ip_mreq,如下:

struct ip_mreq
{
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};

而一台服务器上可能有多个网卡,系统要允许用户使用其中的某个网卡加入某一个主机组,imr_interface参数就是指定一个特定的设备接口,
告诉协议栈只想在这个设备所在的子网中加入某个组播组。有了这两个参数,协议栈就能知道:在哪个网络设备接口上加入哪个组播组。

下面是一个组播的例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <errno.h> #include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/if.h>
#include <linux/route.h>
#include <netinet/ether.h>
#include <netpacket/packet.h>
#include "server.h" bool mySystem(const char *command)
{
int status;
status = system(command); if (- == status)
{
printf("mySystem: system error!");
return false;
}
else
{
if (WIFEXITED(status))
{
if ( == WEXITSTATUS(status))
{
return true;
}
printf("mySystem: run shell script fail, script exit code: %d\n", WEXITSTATUS(status));
return false;
}
printf("mySystem: exit status = [%d]\n", WEXITSTATUS(status));
return false;
}
} void fillRspHead(char *buff, char type)
{
if (type == 'g')
{
memcpy(buff, "getmac|", );
}
else if (type == 's')
{
memcpy(buff, "setip|", );
}
else
{
printf("fillRspHead: invalid command type!\n");
return;
}
}
void fillSN(char *buff)
{
FILE *fp;
int bufflen = strlen(buff);
if((fp=fopen(SN_FILE, "r")) == NULL)
{
strcat(buff, "|");
perror("getSN: fopen");
return;
}
fgets(buff + bufflen, NETLEN, fp);
while(buff[strlen(buff) - ] == '\n' || buff[strlen(buff) - ] == ' ')
{
buff[strlen(buff) - ] = '\0';
}
strcat(buff, "|");
fclose(fp);
} void fillType(char *buff)
{
strcat(buff, HOST_TYPE);
strcat(buff, "|");
} void fillNetworkInfo(char *buff)
{ unsigned char netbuff[NETLEN];
unsigned char temp[NETLEN];
int socketfd;
FILE *gatewayfd;
struct ifreq struReq;
memset(&struReq, , sizeof(struct ifreq));
memset(netbuff, , sizeof(netbuff));
strncpy(struReq.ifr_name, "eth0", sizeof(struReq.ifr_name)); socketfd = socket(PF_INET, SOCK_STREAM, ); if (- == ioctl(socketfd, SIOCGIFHWADDR, &struReq))
{
perror("ioctl hwaddr error!\n");
strcat(buff, "|");
goto fillip;
}
strcpy((char *)netbuff, ether_ntoa((struct ether_addr*)struReq.ifr_hwaddr.sa_data));
strcat(buff, netbuff);
strcat(buff, "|");
fillip:
if (- == ioctl(socketfd, SIOCGIFADDR, &struReq))
{
perror("ioctl ip address error!\n");
strcat(buff, "|");
goto fillnetmask;
}
strcpy((char *)netbuff, inet_ntoa(((struct sockaddr_in *)&(struReq.ifr_addr))->sin_addr));
strcat(buff, netbuff);
strcat(buff, "|");
fillnetmask:
if (- == ioctl(socketfd, SIOCGIFNETMASK, &struReq))
{
perror("ioctl net mask error!\n");
strcat(buff, "|");
goto fillgateway;
}
strcpy((char *)netbuff, inet_ntoa(((struct sockaddr_in *)&(struReq.ifr_netmask))->sin_addr));
strcat(buff, netbuff);
strcat(buff, "|");
fillgateway:
if(gatewayfd = popen("route -n | grep 'UG'", "r"))
{
fread(temp, , NETLEN, gatewayfd);
sscanf(temp, "%*s%s", netbuff);
strcat(buff, netbuff);
}
else
{
perror("fillNetworkInfo: popen!");
strcat(buff, "|");
} pclose(gatewayfd);
close(socketfd); return;
} bool matchMAC(char *buff)
{
unsigned char reqmac[NETLEN];
unsigned char mymac[NETLEN]; unsigned char *start;
int socketfd;
struct ifreq struReq;
memset(reqmac, , sizeof(reqmac));
memset(mymac, , sizeof(mymac));
memset(&struReq, , sizeof(struct ifreq));
strncpy(struReq.ifr_name, "eth0", sizeof(struReq.ifr_name)); socketfd = socket(PF_INET, SOCK_STREAM, ); if (- == ioctl(socketfd, SIOCGIFHWADDR, &struReq))
{
perror("ioctl hwaddr error!\n");
return false;
}
strcpy((char *)mymac, ether_ntoa((struct ether_addr*)struReq.ifr_hwaddr.sa_data));
if ((start = strchr(buff, '|')) == NULL)
{
printf("matchMAC: invalid msg format from rackman!\n");
return false;
}
printf("mac in req =%s, mac myself =%s\n", start+, mymac);
if (strncmp(mymac, start + , strlen(mymac)) == )
{
#ifdef DEBUG
printf("mac matched!\n");
#endif
return true;
}
#ifdef DEBUG
printf("mac not matched!\n");
#endif
return false;
} void splitReq(char *buff, char save[][NETLEN])
{
char *p;
int i = ;
p = strtok(buff, "|");
while(i < REQ_PART_NUM)
{
if (!p)
{
printf("splitReq:the %drd part info is empty!\n", i+);
}
else
{
#ifdef DEBUG
printf("%s\n", p);
#endif
strcpy(save[i], p);
}
p = strtok(NULL, "|");
i++;
}
} bool setNetwork(const char *ipaddr, const char *netmask, const char *gateway)
{
struct ifreq ifr;
struct sockaddr_in saddr;
struct rtentry rte;
struct sockaddr_in rtdst;
struct sockaddr_in rtgw;
if (NULL == ipaddr || NULL == netmask || NULL == gateway)
{
printf("writeConfig: invalid network parameters!\n");
return false;
}
int fd = socket(AF_INET, SOCK_DGRAM, );
if (fd == -)
{
printf("setInterface: Failed to create socket: %s", strerror(errno));
return false;
} memset(&ifr, , sizeof(ifr));
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ); memset(&saddr, , sizeof(saddr));
saddr.sin_family = AF_INET;
inet_aton(ipaddr, &saddr.sin_addr);
memcpy(&ifr.ifr_addr, &saddr, sizeof(saddr)); if (ioctl(fd, SIOCSIFADDR, &ifr) == -)
{
printf("setInterface: Failed to set interface address %s: %s", ipaddr, strerror(errno));
close(fd);
return false;
} inet_aton(netmask, &(((struct sockaddr_in*)&(ifr.ifr_netmask))->sin_addr));
if (ioctl(fd, SIOCSIFNETMASK, &ifr) == -)
{
printf("setInterface: Failed to set interface netmask %s: %s", netmask, strerror(errno));
close(fd);
return false;
} memset(&rte, , sizeof(rte));
rte.rt_flags = RTF_UP | RTF_GATEWAY;
memset(&rtdst, , sizeof(rtdst));
rtdst.sin_family = AF_INET;
memcpy(&rte.rt_dst, &rtdst, sizeof(rtdst));
ioctl(fd, SIOCDELRT, &rte); memset(&rtgw, , sizeof(rtgw));
rtgw.sin_family = AF_INET;
inet_aton(gateway, &rtgw.sin_addr);
memcpy(&rte.rt_gateway, &rtgw, sizeof(rtgw));
if (ioctl(fd, SIOCADDRT, &rte) == -)
{
printf("setInterface: Failed to add gateway %s: %s", gateway, strerror(errno));
close(fd);
return false;
} close(fd);
return true;
} bool writeConfig(const char *ipaddr, const char *netmask, const char *gateway)
{
char wbuff[BUFLEN];
#ifdef MCPU
FILE *fp;
char rbuff[BUFLEN];
if (NULL == ipaddr || NULL == netmask || NULL == gateway)
{
printf("writeConfig: invalid network parameters!\n");
return false;
}
if((fp=fopen(SYS_NETWORK_FILE, "r+")) == NULL)
{
perror("writeConfig: fopen error!");
return false;
}
while (!feof(fp))
{
fgets(rbuff, BUFLEN, fp);
if (rbuff[] == '#')
{
continue;
}
if (strncmp(rbuff, "iface eth0", ) == )
{
sprintf(wbuff, "address %s\n", ipaddr);
fputs(wbuff, fp);
sprintf(wbuff, "netmask %s\n", netmask);
fputs(wbuff, fp);
sprintf(wbuff, "gateway %s\n", gateway);
fputs(wbuff, fp);
sprintf(wbuff, "route add default gw %s dev eth0\n", gateway);
fputs(wbuff, fp);
fclose(fp);
return true;
}
}
sprintf(wbuff, "echo auto eth0 >> %s", SYS_NETWORK_FILE);
mySystem(wbuff);
sprintf(wbuff, "echo iface eth0 inet static >> %s", SYS_NETWORK_FILE);
mySystem(wbuff);
sprintf(wbuff, "echo address %s >> %s", ipaddr, SYS_NETWORK_FILE);
mySystem(wbuff);
sprintf(wbuff, "echo netmask %s >> %s", netmask, SYS_NETWORK_FILE);
mySystem(wbuff);
sprintf(wbuff, "echo gateway %s >> %s", gateway, SYS_NETWORK_FILE);
mySystem(wbuff);
sprintf(wbuff, "route add default gw %s dev eth0 >> %s", gateway, SYS_NETWORK_FILE);
mySystem(wbuff);
return true;
#else
sprintf(wbuff, "sed -i \"/IPADDR/s/=.*/=%s/\" %s", ipaddr, SYS_NETWORK_FILE);
mySystem(wbuff);
sprintf(wbuff, "sed -i \"/NETMASK/s/=.*/=%s/\" %s", netmask, SYS_NETWORK_FILE);
mySystem(wbuff);
sprintf(wbuff, "sed -i \"/GATEWAY/s/=.*/=%s/\" %s", gateway, SYS_NETWORK_FILE);
mySystem(wbuff);
return true;
#endif
}
void sendRsp(int sockfd, struct sockaddr_in *clntaddr, char *rsp)
{
if (sendto(sockfd, rsp, strlen(rsp), , (struct sockaddr *) clntaddr, sizeof(struct sockaddr_in)) < )
{
perror("sendRsp: sendto!");
return;
}
#ifdef DEBUG
printf("send msg to client ok: %s\n", rsp);
#endif
} bool addHostGroup(int recvfd)
{
struct hostent *group;
struct ip_mreq mreq;
struct in_addr ia;
bzero(&mreq, sizeof(struct ip_mreq)); if ((group = gethostbyname(MULTI_CAST_ADDR)) == (struct hostent *) )
{
perror("gethostbyname");
return false;
} bcopy((void *) group->h_addr, (void *) &ia, group->h_length); bcopy(&ia, &mreq.imr_multiaddr.s_addr, sizeof(struct in_addr)); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(recvfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) == -)
{
perror("addHostGroup: setsockopt!");
return false;
}
return true;
} bool bindSocket(int recvfd, int sendfd)
{
struct sockaddr_in recvaddr, sendaddr;
int socklen = sizeof(struct sockaddr_in); memset(&recvaddr, , socklen);
memset(&sendaddr, , socklen);
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(MULTI_CAST_PORT);
if (inet_pton(AF_INET, MULTI_CAST_ADDR, &recvaddr.sin_addr) <= )
{
perror("bindSocket: inet_pton error!");
return false;
} if (bind(recvfd, (struct sockaddr *) &recvaddr, socklen) == -)
{
perror("bindSocket: bind recvfd error!");
return false;
} sendaddr.sin_family = AF_INET;
sendaddr.sin_port = htons(RACKMAN_LISTEN_PORT);
sendaddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sendfd, (struct sockaddr *) &sendaddr, socklen) == -)
{
perror("bindSocket: bind sendfd error!");
return false;
} return true;
} int main(int argc, char **argv)
{
struct sockaddr_in clntaddr; int recvfd, sendfd;
char recmsg[BUFLEN + ];
char rspmsg[BUFLEN + ];
char netinfo[REQ_PART_NUM][NETLEN];
unsigned int socklen, n;
char *addr;
bool ret; //create socket
recvfd = socket(AF_INET, SOCK_DGRAM, );
sendfd = socket(AF_INET, SOCK_DGRAM, );
if (recvfd < || sendfd < )
{
printf("socket creating err in udptalk\n");
return -;
}
if (addHostGroup(recvfd) == false)
{
printf("server: addHostGroup error!\n");
close(recvfd);
close(sendfd);
return -;
}
if (bindSocket(recvfd, sendfd) == false)
{
printf("server: bindSocket error!\n");
close(recvfd);
close(sendfd);
return -;
} while()
{
bzero(recmsg, BUFLEN + );
bzero(rspmsg, BUFLEN + );
socklen = sizeof(struct sockaddr_in);
n = recvfrom(recvfd, recmsg, BUFLEN, , (struct sockaddr *) &clntaddr, &socklen);
if (n < )
{
perror("Rackman server: recvfrom error!");
continue;
}
//receive msg from rackman client
recmsg[n] = ;
#ifdef DEBUG
addr = (char *)inet_ntoa(clntaddr.sin_addr);
printf("client address = %s, port = %d\n", addr, ntohs(clntaddr.sin_port));
printf("receive msg from client: %s\n", recmsg);
#endif
clntaddr.sin_port = htons(RACKMAN_LISTEN_PORT);
if (inet_pton(AF_INET, RACKMAN_MULTI_CAST_ADDR, &clntaddr.sin_addr) <= )
{
perror("inet_pton: inet_pton error!");
return -;
}
fillRspHead(rspmsg, recmsg[]);
if (strncmp(recmsg, "setip", ) == )
{
if (matchMAC(recmsg))
{
splitReq(recmsg, netinfo);
#ifdef DEBUG
printf("setip: ip = %s, netmask = %s, gateway = %s\n", netinfo[], netinfo[], netinfo[]);
#endif
ret = setNetwork((const char *)netinfo[], (const char *)netinfo[], (const char *)netinfo[]);
if (ret == true)
{
strcat(rspmsg, "success|");
writeConfig((const char *)netinfo[], (const char *)netinfo[], (const char *)netinfo[]);
}
else
{
strcat(rspmsg, "failed|");
}
}
else
{
continue;
}
}
fillSN(rspmsg);
fillType(rspmsg);
fillNetworkInfo(rspmsg);
sendRsp(sendfd, &clntaddr, rspmsg);
}
}

.h文件:

#ifndef MULTICAST_SERVER_H
#define MULTICAST_SERVER_H #define MULTI_CAST_ADDR "234.5.6.7"
#define MULTI_CAST_PORT (4567)
#define RACKMAN_MULTI_CAST_ADDR "234.5.6.8"
#define RACKMAN_LISTEN_PORT (4568)
#define BUFLEN 300
#define NETLEN 100
#define REQ_PART_NUM 5 #ifdef MCPU
#define SN_FILE "/MCPUSN"
#define HOST_TYPE "mcpu"
#define SYS_NETWORK_FILE "/etc/network/interfaces"
#else
#define SN_FILE "/nandflash/chassisSN"
#define HOST_TYPE "bmc"
#define SYS_NETWORK_FILE "/nandflash/network" #endif typedef enum
{
false,
true
}bool;
#endif

udp组播的实现的更多相关文章

  1. Android设备一对多录屏直播--(UDP组播连接,Tcp传输)

    原文:https://blog.csdn.net/sunmmer123/article/details/82734245 近期需要学习流媒体知识,做一个Android设备相互投屏Demo,因此找到了这 ...

  2. ffmpeg笔记——UDP组播接收总结

    ffmpeg在avformat_open_input里面已经实现了UDP的协议,所以只需要设置好参数,将url传递进去就可以了. 和打开文件的方式基本一样: 01 AVCodecContext *pV ...

  3. C# 使用UDP组播实现局域网桌面共享

    最近需要在产品中加入桌面共享的功能,暂时不用实现远程控制:参考了园子里的一些文章,加入了一些自己的修改. 需求:将一台机器的桌面通过网络显示到多个客户端的屏幕上,显示内容可能为PPT,Word文档之类 ...

  4. Android上UDP组播无法接收数据的问题

    最近,想做一个跨平台的局域网的文件传输软件,思路是组播设备信息,TCP连接传输文件.于是进行了一次简单的UDP组播测试,发现Android对于UDP组播接收数据的支持即极为有限. 部分代码如下 pac ...

  5. 【网络开发】UDP组播接收端解析

    UDP组播接收端解析 网络中的一台主机如果希望能够接收到来自网络中其它主机发往某一个组播组的数据报,那么这么主机必须先加入该组播组,然后就可以从组地址接收数据包.在广域网中,还涉及到路由器支持组播路由 ...

  6. 多网卡情况下接收udp组播

    多网卡下接收udp组播 往往会接收失败 因为用错了网卡 例如我想要接收2网段 其他电脑出的udp组播  我电脑有有线网和wifi在window下可以这样 route add 230.0.0.1 mas ...

  7. (转)C# 使用UDP组播实现局域网桌面共享

    转:http://www.cnblogs.com/mobwiz/p/3715743.html 最近需要在产品中加入桌面共享的功能,暂时不用实现远程控制:参考了园子里的一些文章,加入了一些自己的修改. ...

  8. 调皮的udp组播技术

    2017年本科毕业,经历过千辛万苦的找工作之后,我进入了现在的这家公司.虽是职场小白,但励志成为IT界的一股清流(毕竟开发的妹子少,哈哈).因为公司的业务需要,我负责的部分是利用组播技术实现OSG模型 ...

  9. 桌面共享UDP组播实现

    组播(Multicast)传输:在发送者和每一接收者之间实现点对多点网络连接.如果一台发送者同时给多个的接收者传输相同的数据,也只需复制一份的相同数据包.它提高了数据传送效率.减少了骨干网络出现拥塞的 ...

  10. 课堂/会议同屏教学解决方案之RTSP/RTP over UDP组播解决方案

    问题 在之前的博客<EasyIPCamera实现Windows PC桌面.安卓Android桌面同屏直播,助力无纸化会议系统>我们描述了一套基于EasyIPCamera的同屏功能,但是这个 ...

随机推荐

  1. docker之本地连接

    docker安装成功,之后我们需要连接进入docker中,这里罗列连接方式 1. Windows7 一般的虚拟ip地址: 192.168.99.100 查看ip地址: 1)  C:\Users\thi ...

  2. 简单Delphi程序设计

  3. php中禁止单个ip与ip段访问的代码小结

    1.禁止单个IP <?php //IP访问限制 if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP' ...

  4. DevExpress WPF v19.1新版亮点:主题/Tree List等控件新功能

    行业领先的.NET界面控件DevExpress 日前正式发布v19.1版本,本站将以连载的形式介绍各版本新增内容.在本系列文章中将为大家介绍DevExpress WPF v19.1中新增的一些控件及部 ...

  5. SpringCloud学习系列-Eureka服务注册与发现(1)

    1.Eureka的基本架构 Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务注册和发现(请对比Zookeeper). Eureka 采用了 C-S 的设计架构 ...

  6. WinServer2008R2远程桌面长时间保持连接

    开始------运行------gpedit.msc 计算机配置------管理模板-----Windows组件-----远程桌面服务------远程桌面会话主机------会话时间限制 修改两项设置 ...

  7. 20180705 SSH,SSM

    1.数据源切换2.数据库SQL server 2008R23.Herbernate,MyBaits, 框架spring mvc hibernate mybatis maven 管理 登录 spring ...

  8. 电脑右键新建没有xmind文件选项解决方法

    xmind还是方便的. 打开注册表,展开HKEY_CLASSES_ROOT,展开.xmind(如果没有请新建).在里面新建ShellNew项,并展开,在里面新建NullFile这个字符串值. 如果还是 ...

  9. SQL基础-order by

    若sql语句中order by指定了多个字段,则怎么排序? 举个例子吧:order by id desc,time desc 先是按 id 降序排列  (优先)如果 id 字段 有些是一样的话   再 ...

  10. consul windows下搭建

    起源 由于项目在linux部署,但是开发和测试是在windows下的,所以,暂时接触到consul,暂时也不会远程连接,只好在windows下安装consul 过程 去官网下载:https://www ...