组播在内核里面对应的一个重要的结构体是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. 使用elasticdump导入导出数据

    一.安装elasticdump 终端中输入 npm install elasticdump -g -g表示全局可用,直接在终端输入 elasticdump --version,出现版本信息即表示安装成 ...

  2. python模块导入总结

    python模块导入总结 模块导入方式 定义test.py模块 def print_func(): print("hello") import 语句 导入模块语法 import m ...

  3. 企业级开发账号In House ipa发布流程

    这两天需要发布一个ipa放到网上供其他人安装,需要用到企业级开发者账号.在网上查了一下资料,感觉没有一个比较完善的流程,于是决定把整个流程写下来,供大家参考. 首先详细说明一下我们的目标,我们需要发布 ...

  4. 工具使用——使用XShell连接linux系统

    1.首先到官网取下载一个XShell安装包,根据提示安装成功. 2.打开软件,点击新建连接 3.在新建连接页面输入,主机名称.主机地址.端口号,点击确定按钮. 4.在弹出的会话窗口中,选中我们刚刚创建 ...

  5. PAT Advanced 1041 Be Unique (20 分)

    Being unique is so important to people on Mars that even their lottery is designed in a unique way. ...

  6. Codeforces1203F2. Complete the Projects (hard version) (贪心+贪心+01背包)

    题目链接:传送门 思路: 对于对rating有提升的项目,肯定做越多越好,所以把$b_{i} >= 0$的项目按rating要求从小到大贪心地都做掉,得到最高的rating记为r. 对于剩余的$ ...

  7. java数据结构3--List

    List 1.1 list接口的简介 1.2 list实现子类 ArrayList:线程不安全,查询速度快,底层用的是数组,增删慢LinkedList:线程不安全,链表结构,增删速度快,查询慢Vect ...

  8. docker安装各类软件

    安装Docker Docker 要求 CentOS 系统的内核版本高于 3.10 , uname -r 命令查看你当前的内核版本 1 安装一些必要的系统工具: sudo yum install -y ...

  9. shell练习--PAT题目1005:继续(3n+1)猜想(全绿失败喜加一)

    卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数.例如对 n=3 进行验证的时 ...

  10. Ubuntu下安装CUDA8.0及nvidia驱动

    参考:https://blog.csdn.net/qq_35379989/article/details/80147630 cuda的历史版本下载地址:https://developer.nvidia ...