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的同屏功能,但是这个 ...
随机推荐
- java复习(1)面向对象
一.面向对象的概念 ----------------------------------------------------- 1.理解面向对象:(1)面向对象是相对于面向过程的语言 (2)面向对象和 ...
- window常见事件onload
1, window.onload 是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像,脚本文件,css文件等),就调用的处理函数 下面的代码,当点击按钮,并不会弹出对话框,因为页面还 ...
- GitHub源码攻击事件
黑客擦除了微软多达392个代码存储库,并提出勒索要求.此前,黑客攻击了包含微软在内的大批受害者的Git存储库,删除了所有源代码和最近提交的内容,并留下了支持比特币支付的赎金票据. 勒索信息如下: “要 ...
- JavaNIO
Java New IO 简称 nio,在jdk1.4提供了新的api,有如下特性: 1.为所有原始类型提供缓存支持 2.字符集编解码解决方案 3.Channel:新的原始io抽象 4.支持锁和内存映射 ...
- Jmeter分布式测试dubbo接口2
上次我们将dubbo接口与jmeter集成起来,但是jmeter是由java实现的,本身有很多限制,无法实现高并发,我们需要借助分布式来实现大压力测试. 在上次的例子中,我们只是实现了简单的dubbo ...
- BZOJ3745 / SP22343 NORMA2 - Norma 分治,CDQ分治
要命的题目. 写法:分类讨论进行计算. 枚举过每一个\(mid\)的所有区间.对于左端点\(i∈[l, mid - 1]\),向左推并计算\([l,mid]\)范围内的最大\(/\)最小值. 然后右端 ...
- golang初识 和 变量,常量,iota
目录 一.go语言与python 1. go语言 2. python 二.变量相关 1. go语言的基本语法 2. 标识符和关键字 3. 变量声明 (1)声明变量时未指定初始值 (2)声明变量时指定初 ...
- JS Null 空 判断
JS判断对象是否为空 https://www.cnblogs.com/mountain-mist/articles/1600995.html http://www.cftea.com/c/2007/0 ...
- shiro框架学习-1-shiro基本概念
1. 什么是权限控制 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源, ...
- DevOps之持续集成Pipeline(一)
一.Pipeline介绍 Jenkins2.0中最大的一个特性就是Pipeline,实际使用中Pipeline已经超越了我们对jenkins本身的理解,可能在之前我们大多数把Jenkins当做 ...