udp组播的实现
组播在内核里面对应的一个重要的结构体是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组播的实现的更多相关文章
- Android设备一对多录屏直播--(UDP组播连接,Tcp传输)
原文:https://blog.csdn.net/sunmmer123/article/details/82734245 近期需要学习流媒体知识,做一个Android设备相互投屏Demo,因此找到了这 ...
- ffmpeg笔记——UDP组播接收总结
ffmpeg在avformat_open_input里面已经实现了UDP的协议,所以只需要设置好参数,将url传递进去就可以了. 和打开文件的方式基本一样: 01 AVCodecContext *pV ...
- C# 使用UDP组播实现局域网桌面共享
最近需要在产品中加入桌面共享的功能,暂时不用实现远程控制:参考了园子里的一些文章,加入了一些自己的修改. 需求:将一台机器的桌面通过网络显示到多个客户端的屏幕上,显示内容可能为PPT,Word文档之类 ...
- Android上UDP组播无法接收数据的问题
最近,想做一个跨平台的局域网的文件传输软件,思路是组播设备信息,TCP连接传输文件.于是进行了一次简单的UDP组播测试,发现Android对于UDP组播接收数据的支持即极为有限. 部分代码如下 pac ...
- 【网络开发】UDP组播接收端解析
UDP组播接收端解析 网络中的一台主机如果希望能够接收到来自网络中其它主机发往某一个组播组的数据报,那么这么主机必须先加入该组播组,然后就可以从组地址接收数据包.在广域网中,还涉及到路由器支持组播路由 ...
- 多网卡情况下接收udp组播
多网卡下接收udp组播 往往会接收失败 因为用错了网卡 例如我想要接收2网段 其他电脑出的udp组播 我电脑有有线网和wifi在window下可以这样 route add 230.0.0.1 mas ...
- (转)C# 使用UDP组播实现局域网桌面共享
转:http://www.cnblogs.com/mobwiz/p/3715743.html 最近需要在产品中加入桌面共享的功能,暂时不用实现远程控制:参考了园子里的一些文章,加入了一些自己的修改. ...
- 调皮的udp组播技术
2017年本科毕业,经历过千辛万苦的找工作之后,我进入了现在的这家公司.虽是职场小白,但励志成为IT界的一股清流(毕竟开发的妹子少,哈哈).因为公司的业务需要,我负责的部分是利用组播技术实现OSG模型 ...
- 桌面共享UDP组播实现
组播(Multicast)传输:在发送者和每一接收者之间实现点对多点网络连接.如果一台发送者同时给多个的接收者传输相同的数据,也只需复制一份的相同数据包.它提高了数据传送效率.减少了骨干网络出现拥塞的 ...
- 课堂/会议同屏教学解决方案之RTSP/RTP over UDP组播解决方案
问题 在之前的博客<EasyIPCamera实现Windows PC桌面.安卓Android桌面同屏直播,助力无纸化会议系统>我们描述了一套基于EasyIPCamera的同屏功能,但是这个 ...
随机推荐
- CentOS7 yum安装配置 +redis主从配置
一.安装必要包 yum install gcc 二.linux下安装 #下载 wget http://download.redis.io/releases/redis-3.0.0.tar.gz tar ...
- Java中Collection、Map常用实现类研究分析
接口/实现类 描述 key是否可为null 为null是否报错 key是否重复 key重复是否报错 key是否和添加一致 是否线程安全 List 一组元素的集合 ArrayList 基于数组存储,读取 ...
- python-函数4(递归、高阶函数)
python-函数4(递归.高阶函数) 递归 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 递归特性: 1. 递归必须有一个明确的结束条件 2. 每次进入更深一 ...
- mysql5.7二进制包进行多实例安装
一.需求 在一台服务器上安装mysql5.7,并且部署两个实例:3306用于本机主库,3307用于其他MYSQL服务器的从库 二.下载mysql二进制包 [root@push-- src]# -lin ...
- [NoSql注入] MongoDB学习
0x00 安装 下载:http://dl.mongodb.org/dl/win32/x86_64 安装:http://www.runoob.com/mongodb/mongodb-window-ins ...
- nginx的反向代理和配置
最近有打算研读nginx源代码,看到网上介绍nginx可以作为一个反向代理服务器完成负载均衡.所以搜罗了一些关于反向代理服务器的内容,整理综合. 一 概述 反向代理(Reverse Proxy)方式 ...
- typedef int(init_fnc_t) (void)的理解
typedef int(init_fnc_t) (void); 这个就是一个取别名的过程. 我们通常情况下会如下使用 typedef :typedef int MyInt;MyInt a; 这个时候我 ...
- PS使用滤镜制作光晕效果
滤镜制作光晕效果 新建图层,将背景色填充为黑色 滤镜->渲染->镜头光晕 调整好光晕大小 通过滤色(图层两字下面一点点的位置,有个下拉菜单,点开就在里面),去黑留白 如果觉得光线不够,可以 ...
- webview默认是不开启localstorage的
.setDomStorageEnabled(true);// 打开本地缓存提供JS调用,至关重要 转载 https://blog.csdn.net/xhf_123/article/details/77 ...
- Linux系统中的硬件问题如何排查?(6)
Linux系统中的硬件问题如何排查?(6) 2013-03-27 10:32 核子可乐译 51CTO.com 字号:T | T 在Linux系统中,对于硬件故障问题的排查可能是计算机管理领域最棘手的工 ...