Linux环境下服务器利用组播来获取客户端IP

单播是两个主机之间端对端通信(比如TCP、UDP通信),而广播用于一个主机对整个局域网中所有主机的通信。单播和广播是两个极端,要么对一个主机通信,要么对局域网内所有主机通信。然而在实际情况下,比如要获取局域网内获取执行特殊任务主机IP,单播显然不适用,因为单播必须首先要知道通信两端的IP,而使用广播显得浪费资源。在这种需要对局域网下一组特定的主机进行通信的情况下,就用到了组播。 本文针对以上情况,从组播概念、组播编程和本机IP地址获取三个方面展开阐述。

什么是组播?

组播就是将网络中同一业务类型的主机进行逻辑上的分组,进行数据收发的时候,数据仅仅仅仅在同一分组内进行,没有加入分组的主机不能收发对应的数据。
说的更通俗一点,主机好比你qq中的联系人,组播组就好比你新建的讨论组,只有加入讨论组的成员才能接受发送消息。

组播地址

说起组播地址就不得不说一下IP地址的分类。IP地址共分为五类,分别是A类、B类、C类、D类和E类。五类不同的IP地址。

5类IP地址:

类别 固定最高位 网络位 第一字节范围
A 0 8 0~127
B 10 16 128~191
C 110 24 192~223
D 1110 组播地址 224~239
E 11110 预留 240~255

D类的IP地址就是组播IP地址。其中,组播IP地址又分为局部组播地址、预留组播地址和管理权限组播地址。

  • 局部组播地址:在224.0.0.0~224.0.0.255之间,这个区间的地址视为路由协议和其他用途保留的地址,路由器并不妆发范围的IP包。
  • 预留组播地址:在224.0.1.0~238.255.255.255之间,可用于路由协议。
  • 管理权限组播地址:在239.0.0.0~239.255.255.255之间,类似于私有地址,不能用于网络。

获取本机IP地址

主要用到了ioctl 函数(设备控制接口)来从网卡中获取IP信息和主机信息。顾名思义,ioctl函数就是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数如下:

int ioctl(int fd, ind cmd, …); 

其中fd是用户程序打开设备时使用open函数返回的文件标示符,cmd是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,这个参数的有无和cmd的意义相关。
ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数来控制设备的I/O通道。
获取本机IP地址和主机名的完整代码如下:

#define ETH_NAME "eth"void getIPHost(char** iphost)
{int sock;struct sockaddr_in   sin;struct ifreq   ifr;sock  = socket(AF_INET, SOCK_DGRAM, 0);for(int i = 0; i < 10; i++){char* ENAME = (char*)malloc(5*sizeof(char));bzero(ENAME, 5);sprintf(ENAME, "%s%d", ETH_NAME, i);strncpy(ifr.ifr_name,   ENAME,   IFNAMSIZ);free(ENAME);ifr.ifr_name[IFNAMSIZ   -   1]   =   0;if (ioctl(sock,   SIOCGIFADDR,   &ifr)   >=   0)goto HERE;}for(int i = 0; i < 10; i++){char* WNAME = (char*)malloc(6*sizeof(char));bzero(WNAME, 6);sprintf(WNAME, "%s%d", WTH_NAME, i);strncpy(ifr.ifr_name,   WNAME,   IFNAMSIZ);free(WNAME);ifr.ifr_name[IFNAMSIZ   -   1]   =   0;if (ioctl(sock,   SIOCGIFADDR,   &ifr)   >=   0)    goto HERE;}HERE:memcpy(&sin,   &ifr.ifr_addr,   sizeof(sin));char* hostname = (char*)malloc(256*sizeof(char));bzero(hostname, 256);gethostname(hostname, 256*sizeof(char));char* ip = inet_ntoa(sin.sin_addr);int lenhost  = strlen(hostname);int lenip = strlen(ip);*iphost = (char*)malloc((lenhost+lenip+2)*sizeof(char));bzero(*iphost, (lenhost+lenip+2)*sizeof(char));sprintf(*iphost,   "%s:%s",  ip, hostname);free(hostname);
}

这里要注意一下,代码运行时会报“No Such Device”错误,这是由于系统网卡名不是以“eth”开头,只需将ETH_NAME修改成本机网卡名即可。

组播编程

要进行组播编程必须遵从一定的编程框架。基本顺序如下:
接收端:
  1.创建socket
  2. 初始化本机地址信息
  3.绑定socket和本机地址信息
  4.将本机加入组播组
  5.接收消息
发送端:
  1.创建socket
   2. 初始化多播地址
   3.发送数据

组播程序设计使用setsockopt()函数和getsockopt()函数来实现,组播的选项是IP层的。
1.选项IP_MULTICASE_TTL
选项IP_MULTICAST_TTL允许设置超时TTL,范围为0~255之间的任何值,例如:

unsigned char ttl=255;
setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl)); 

2.选项IP_MULTICAST_IF
选项IP_MULTICAST_IF用于设置组播的默认默认网络接口,会从给定的网络接口发送,另一个网络接口会忽略此数据。例如:

struct in_addr addr;
setsockopt(s,IPPROTO_IP,IP_MULTICAST_IF,&addr,sizeof(addr));

参数addr是希望多播输出接口的IP地址,使用INADDR_ANY地址回送到默认接口。
默认情况下,当本机发送组播数据到某个网络接口时,在IP层,数据会回送到本地的回环接口,选项IP_MULTICAST_LOOP用于控制数据是否回送到本地的回环接口。例如:

unsigned char loop;
setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));//参数loop设置为0禁止回送,设置为1允许回送。

3.选项IP_ADD_MEMBERSHIP和IP_DROP_MEMBERSHIP
加入或者退出一个多播组。例如:

struct ip_mreq mreq;
setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));

以下为详细代码:

发送端代码:

#define MCAST_PORT 8888;
#define MCAST_ADDR "224.0.0.100"    /*一个局部连接多播地址,路由器不进行转发*/
#define MCAST_INTERVAL 5                            /*发送间隔时间*/
int main(int argc, char*argv)
{int s;char *iphost;struct sockaddr_in mcast_addr;     s = socket(AF_INET, SOCK_DGRAM, 0);         /*建立套接字*/if (s == -1){perror("socket()");return -1;}memset(&mcast_addr, 0, sizeof(mcast_addr));/*初始化IP多播地址为0*/mcast_addr.sin_family = AF_INET;                /*设置协议族类行为AF*/mcast_addr.sin_addr.s_addr = inet_addr(MCAST_ADDR);/*设置多播IP地址*/mcast_addr.sin_port = htons(MCAST_PORT);        /*设置多播端口*//*获取本机地址*/getIPHost(&iphost);/*向多播地址发送数据*/while(1) {int n = sendto(s,        /*套接字描述符*/iphost,     /*数据*/sizeof(iphost),    /*长度*/0,(struct sockaddr*)&mcast_addr,sizeof(mcast_addr)) ;if( n < 0){perror("sendto()");return -2;}      sleep(MCAST_INTERVAL);                          /*等待5s*/}return 0;
}

接收端代码:

#define MCAST_PORT 8888;
#define MCAST_ADDR "224.0.0.100"     /*一个局部连接多播地址,路由器不进行转发*/
#define MCAST_INTERVAL 5                        /*发送间隔时间*/
#define BUFF_SIZE 256                           /*接收缓冲区大小*/
int main(int argc, char*argv[])
{  int s;                                      /*套接字文件描述符*/struct sockaddr_in local_addr;              /*本地地址*/int err = -1;s = socket(AF_INET, SOCK_DGRAM, 0);     /*建立套接字*/if (s == -1){perror("socket()");return -1;}  /*初始化地址*/memset(&local_addr, 0, sizeof(local_addr));local_addr.sin_family = AF_INET;local_addr.sin_addr.s_addr = htonl(INADDR_ANY);local_addr.sin_port = htons(MCAST_PORT);/*绑定socket*/err = bind(s,(struct sockaddr*)&local_addr, sizeof(local_addr)) ;if(err < 0){perror("bind()");return -2;}/*设置回环许可*/int loop = 1;err = setsockopt(s,IPPROTO_IP, IP_MULTICAST_LOOP,&loop, sizeof(loop));if(err < 0){perror("setsockopt():IP_MULTICAST_LOOP");return -3;}struct ip_mreq mreq;                                    /*加入多播组*/mreq.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR); /*多播地址*/mreq.imr_interface.s_addr = htonl(INADDR_ANY); /*网络接口为默认*//*将本机加入多播组*/err = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq, sizeof(mreq));if (err < 0){perror("setsockopt():IP_ADD_MEMBERSHIP");return -4;}int times = 0;int addr_len = 0;char buff[BUFF_SIZE];int n = 0;/*循环接收多播组的消息,5次后退出*/for(times = 0;times<5;times++){addr_len = sizeof(local_addr);memset(buff, 0, BUFF_SIZE);                 /*清空接收缓冲区*//*接收数据*/n = recvfrom(s, buff, BUFF_SIZE, 0,(struct sockaddr*)&local_addr,&addr_len);if( n== -1){perror("recvfrom()");}/*打印信息*/printf("Recv %dst message from server:%s\n", times, buff);sleep(MCAST_INTERVAL);}/*退出多播组*/err = setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP,&mreq, sizeof(mreq));close(s);return 0;
}

Linux环境下服务器利用组播来获取客户端IP相关推荐

  1. Linux环境下服务器 Tomcat war包部署步骤

    当前工作环境是 Tomcat 8.5.31 1.常规方式 1.通过IDE打包成war 2.上传到tomcat里webapps目录下 3.重启Tomcat Note:这里注意的url后添加项目名,也就是 ...

  2. linux 环境下配置ftp服务器

      之前写了 linux 环境下安装和配置mysql数据库以及远程登录,以及linux 环境下配置python虚拟环境,这一篇记录一下 linux系统中如何安装配置 ftp .    安装ftp // ...

  3. linux cvs服务,Linux环境下轻松搭建CVS服务器

    CVS是一种广泛应用的.开源的.透明于网络的版本控制系统.用户使用CVS时,首先要架设一台CVS服务器,在CVS服务器上导入项目实例.设置CVS项目访问控制等.而客户则通过客户端来访问CVS服务器,客 ...

  4. linux环境下随时照看服务器进程的ps和top命令

    文章目录 前言 ps命令 语法格式 语法规范 常用的ps选项 ps命令的表头 进程状态 常规状态码 BSD格式状态码 进程相关的后续命令 top命令 语法格式 常用的top选项和快捷键 top命令的表 ...

  5. 【 Linux学习】Linux环境下利用OpenSSL对大文件进行AES加解密

    一.背景 之前的几篇博客已经介绍了Gitlab如何备份恢复与迁移已经脚本监控过程等. git学习--> Gitlab如何进行备份恢复与迁移? http://blog.csdn.net/ouyan ...

  6. 在Linux环境下mysql的root密码忘记解决方法 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库。 2.修改MySQL的登录设置: # vi /etc/my.c

    在Linux环境下mysql的root密码忘记解决方法 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 2.修改MySQL的登录设置: # vi /etc/my.cnf ...

  7. 服务器Linux环境下安装Matlab2018b

    服务器Linux环境下安装Matlab2018b 一.下载Linux版本Matlab2018b 二.上传Matlab2018b镜像 三.安装Matlab2018b 四.激活Matlab 一.下载Lin ...

  8. linux 下搭建portal服务器搭建,Linux环境下IBM WebSphere Portal v8.5独立服务器安装记录...

    本文用于说明在Linux环境下IBM WebSphere Portal v8.5独立服务器的安装记录: 环境说明: 硬件环境:Lenovo E440, i7, 12GB, 500GB: 虚拟设备:VM ...

  9. 服务器远程连接控制以及在Linux环境下安装go编译环境

    本文主要内容 一.xshell远程控制服务器 二.VS code远程控制服务器 三.在Linux环境下安装go编译环境 初学者在没有人的指导下自己摸索学习真的是太难了,回想一下从大二创新实践开始到现在 ...

最新文章

  1. python的一些基本语法
  2. vscode 设置缩进为4_VS Code 设置缩进为4个空格
  3. 8、oracle数据库下的索引
  4. spring security method security
  5. 跟随我在oracle学习php(51)
  6. 【AI视野·今日NLP 自然语言处理论文速览 第十九期】Mon, 5 Jul 2021
  7. Windows进程同步之事件内核对象(Event)
  8. 【重磅分享】从零到一搭建推荐系统指南白皮书.pdf(附48页下载链接)
  9. 开源软件运动为什么流行起来?
  10. 使用mysql悲观锁解决并发问题
  11. java开启注解扫描,详解Spring框架注解扫描开启之配置细节
  12. Starting MySQL. ERROR! The server quit without updating PID file
  13. 2022-Java面试宝典收藏版
  14. 数据同步工具简单介绍
  15. netware php_服务器_如何在 Netware 服务器中安装多块网卡,如果网络在扩大时服务器只装 - phpStudy...
  16. 树莓派41/100- Pico控制触摸开关模块TTP223
  17. element-ui table表格。数组对应的一组数据占有两行怎么处理?
  18. Oauth2 存储 token 到Redis 报错:READONLY You can‘t write against a read only slave
  19. 【安全】漏洞挖掘之王的传奇人生
  20. JPG图片插入到CAD图纸中的2种方法

热门文章

  1. 移远EC200T 4G LTE模块在MDK9X25L-EK(AT91SAM9X25)平台的应用演示
  2. Tanh函数代码实现
  3. decltype关键字详解
  4. Python实验1 流程控制
  5. Python机器学习基础教程1
  6. 心随羽动,轻羽飞扬-坚持
  7. 【写作能力提升】“5种搭建⽂章架构的⽅法”免费赠送!
  8. Vue生产环境和开发环境的配置
  9. 鸿蒙科学实验课,魔力科学小实验 | 画在盘子上的人像居然变活了!很少人发现这个秘密...
  10. C# Solidworks二次开发:删除螺纹孔