首页 技术 正文
技术 2022年11月9日
0 收藏 741 点赞 4,753 浏览 10203 个字

组播在内核里面对应的一个重要的结构体是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"#endiftypedef enum
{
false,
true
}bool;
#endif
上一篇: kafka操作命令
下一篇: 2、Shiro的认证
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,487
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,903
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,736
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,486
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,126
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,287