Linux网络编程- struct packet_mreq setsockopt()
struct packet_mreq
struct packet_mreq
是一个数据结构,用于 Linux 中的原始数据包套接字,当我们想改变套接字的行为以接收特定类型的数据包时,它与 setsockopt()
函数配合使用。
下面是 struct packet_mreq
的定义:
struct packet_mreq {int mr_ifindex; // Interface index of the network deviceunsigned short mr_type; // Type of membership (e.g., PACKET_MR_PROMISC, PACKET_MR_MULTICAST)unsigned short mr_alen; // Address lengthunsigned char mr_address[8]; // Physical layer address
};
各字段的详细解释:
-
mr_ifindex:
- 这是网络接口的索引号。我们可以使用
if_nametoindex()
函数,将接口名称(如 “eth0”)转换为其索引。(注:if_nametoindex(iface_name) 函数用于将网络接口名称(如 “eth0”)转换为与该接口关联的接口索引。接口索引是内核用于唯一标识网络接口的整数。当 if_nametoindex 函数不能找到指定名称的网络接口时,它会返回0。因此,检查返回值是否为0可以告诉我们是否成功获取了接口索引。)
- 这是网络接口的索引号。我们可以使用
-
mr_type:
- 这是要修改的成员资格类型。例如:
PACKET_MR_PROMISC
: 设置接口为混杂模式。PACKET_MR_MULTICAST
: 加入多播组。PACKET_MR_UNICAST
: 添加一个单播地址。PACKET_MR_ALLMULTI
: 接收所有多播数据包。PACKET_MR_BROADCAST
: 接收所有广播数据包。
- 这是要修改的成员资格类型。例如:
-
mr_alen:
- 用于指定在
mr_address
字段中的物理地址长度。例如,对于以太网地址,这将是6。
- 用于指定在
-
mr_address:
- 物理层地址。这通常是以太网MAC地址,但长度取决于实际的物理层。例如,当
mr_type
为PACKET_MR_MULTICAST
时,我们将在此字段中指定要加入的多播地址。
- 物理层地址。这通常是以太网MAC地址,但长度取决于实际的物理层。例如,当
例如,如果想将网络接口 “eth0” 设置为混杂模式,可以这样做:
struct packet_mreq mr;
memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = if_nametoindex("eth0");
mr.mr_type = PACKET_MR_PROMISC;
setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr));
而如果想加入一个特定的多播地址,则设置 mr_type
为 PACKET_MR_MULTICAST
,并提供相应的多播MAC地址。
示例
本例展示了如何为特定的网络接口(例如 “eth0”)设置混杂模式,并加入一个特定的多播地址。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <net/if.h>
#include <arpa/inet.h>int main() {int sock;struct packet_mreq mr;const char* iface_name = "eth0";// 创建一个原始套接字sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));if (sock < 0) {perror("Error in socket creation");exit(EXIT_FAILURE);}// 设置网络接口为混杂模式memset(&mr, 0, sizeof(mr));mr.mr_ifindex = if_nametoindex(iface_name);if (mr.mr_ifindex == 0) {perror("Error getting interface index");exit(EXIT_FAILURE);}mr.mr_type = PACKET_MR_PROMISC;if (setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0) {perror("Error setting socket to promiscuous mode");exit(EXIT_FAILURE);}// 假设我们要加入的多播MAC地址是 "01:00:5E:10:20:30"unsigned char multicast_address[6] = {0x01, 0x00, 0x5E, 0x10, 0x20, 0x30};mr.mr_type = PACKET_MR_MULTICAST;mr.mr_alen = 6;memcpy(mr.mr_address, multicast_address, 6);if (setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0) {perror("Error adding multicast membership");exit(EXIT_FAILURE);}printf("Interface %s set to promiscuous mode and joined multicast address 01:00:5E:10:20:30.\n", iface_name);// ... 这里可以添加其他代码,例如数据包捕获和处理close(sock);return 0;
}
上述代码首先为 “eth0” 网络接口设置混杂模式,然后加入了特定的多播MAC地址 “01:00:5E:10:20:30”。需要有适当的权限来执行这个代码(通常需要root权限)。
加入特定的多播MAC地址允许网络接口接收发送到该特定多播地址的数据包。这与多播的基本工作方式有关。这里是一个简要的概述:
-
多播:多播是在IP网络上向多个接收者发送信息的方法,但不是向所有接收者发送信息(这称为广播)。多播发送的数据包被发送到一个特定的多播IP地址,并由加入该多播组的接收者接收。
-
多播MAC地址:由于数据链路层(例如以太网)并不了解IP地址,因此IP多播地址被映射到一个特定的MAC地址范围。这意味着,当一个多播数据包在以太网上发送时,它实际上是发送到一个特定的多播MAC地址。
-
加入多播组:如果应用程序对某个多播组感兴趣(即,它想要接收发送到该组的数据包),则需要告诉我们的网络接口加入该组。这样,当接口看到发送到相关多播MAC地址的数据包时,它就知道需要接收它们,而不是忽略它们。
-
用途:
- 多播视频和音频流:例如,一个服务器可以将实时视频流发送到多播地址,而所有希望查看该视频流的客户端只需加入相关的多播组即可。
- 路由协议:一些路由协议使用多播来交换路由信息。
- 服务发现:一些协议,如mDNS,使用多播来发现网络上的服务。
- 其他:还有许多其他使用多播的场景,从股票交易到计算机游戏的实时多玩家数据。
总之,通过加入特定的多播MAC地址,我们的网络接口或应用程序可以选择性地接收发送到这些地址的数据包,这对于需要接收特定多播数据的应用程序来说是很有用的。
setsockopt()
setsockopt()
是一个系统调用,用于设置与某个套接字关联的选项。此函数允许应用程序在各种协议级别上设置或更改多种套接字行为。
以下是 setsockopt()
的基本形式:
int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len);
参数解释:
- socket:它是要设置选项的套接字的文件描述符。
- level:这决定了哪个协议的选项应该被设置。例如,要设置TCP选项,可以使用
IPPROTO_TCP
作为级别。常见的级别包括SOL_SOCKET
、IPPROTO_IP
和IPPROTO_TCP
。 - option_name:这是我们想要设置的具体选项的名称。例如,
SO_REUSEADDR
和SO_KEEPALIVE
都是SOL_SOCKET
级别的选项。 - option_value:这是一个指向要设置选项的新值的指针。
- option_len:这是
option_value
指向的数据的大小。
常见用途:
-
端口重用:当套接字关闭后,端口可能会保持在
TIME_WAIT
状态一段时间。如果想立即重启服务器并重新绑定到相同的端口,可以使用SO_REUSEADDR
选项。int optval = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
-
设置发送/接收缓冲区的大小:例如,我们可能希望增大套接字的发送或接收缓冲区。
int bufsize = 1024 * 1024; // 1MB setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
-
TCP 选项:例如,
TCP_NODELAY
选项可以用于禁用 Nagle’s 算法,使得小的数据包可以被更快地发送。int flag = 1; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int));
返回值:
- 成功时返回 0。
- 失败时返回 -1 并设置
errno
。
错误:
EBADF
:描述符不是一个有效的套接字。ENOPROTOOPT
:指定的协议级别不识别该选项。EFAULT
:option_value
指向的内存不是一个有效的部分。
要获取套接字选项的当前值,可以使用 getsockopt()
函数。
注意:具体支持哪些选项和级别可能因操作系统而异,建议查阅特定操作系统的手册页或相关文档以获取详细和完整的信息。
setsockopt()
的 level
和 option_name
参数可以取多种值,具体取决于操作系统。以下是一些常见的选项及其解释:
1. level: SOL_SOCKET
这是通用的套接字选项级别。
-
SO_REUSEADDR:
- 说明:允许套接字和其他套接字绑定到相同的地址和端口。这对于在短时间内多次关闭、打开同一地址、端口的服务器应用程序很有用。
-
SO_KEEPALIVE:
- 说明:如果套接字没有接收到数据,在一段时间后将开始发送keepalive消息。这有助于确保连接仍然活动并确定远程主机是否还在线。
-
SO_RCVBUF 和 SO_SNDBUF:
- 说明:设置或获取接收或发送缓冲区的大小。
-
SO_RCVTIMEO 和 SO_SNDTIMEO:
- 说明:设置或获取接收或发送超时。
-
SO_ERROR:
- 说明:获取套接字上的待处理错误。
-
SO_TYPE:
- 说明:获取套接字的类型。
2. level: IPPROTO_IP
这是IP层的选项。
-
IP_TTL:
- 说明:设置或获取Time To Live字段的值。
-
IP_MULTICAST_IF:
- 说明:指定用于发送多播数据报的出口接口。
-
IP_ADD_MEMBERSHIP 和 IP_DROP_MEMBERSHIP:
- 说明:加入或离开多播组。
-
IP_HDRINCL:
- 说明:指示应用程序将提供完整的IP头部。
3. level: IPPROTO_TCP
这是TCP层的选项。
-
TCP_NODELAY:
- 说明:控制Nagle算法是否用于套接字。这对于希望快速发送小的数据包的应用程序很有用。
-
TCP_MAXSEG:
- 说明:获取或设置TCP最大段大小。
这只是一个简要的概述,实际上有更多的选项和级别可供选择。这些选项的行为、可用性以及如何正确使用它们可能会因操作系统和其版本而异。因此,在使用特定的选项时,最好查阅所使用的操作系统的手册页或其他相关文档。
getsockopt()
getsockopt()
函数用于获取套接字选项。该函数允许应用程序查看或修改套接字的当前选项值。与setsockopt()
类似,getsockopt()
也可以在多种层次上获取选项,例如 SOL_SOCKET(通用套接字层)、IPPROTO_IP(IP层)和IPPROTO_TCP(TCP层)等。
函数原型:
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
参数:
sockfd
:标识套接字的文件描述符。level
:选项定义的级别,例如:SOL_SOCKET、IPPROTO_IP。optname
:需要访问的选项名称,例如:SO_REUSEADDR、TCP_NODELAY。optval
:指向值的指针,该值将被获取。optlen
:作为输入时表示optval
的最大长度,作为输出时表示optval
的实际长度。
返回值:
成功时返回0,失败时返回-1。
示例
以下是使用getsockopt()
获取套接字发送缓冲区大小的示例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>int main(void) {int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {perror("socket");exit(EXIT_FAILURE);}int sendbuff;socklen_t optlen = sizeof(sendbuff);// 获取SO_SNDBUF选项的值if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen) == -1) {perror("getsockopt");close(sockfd);exit(EXIT_FAILURE);}printf("Send buffer size = %d\n", sendbuff);close(sockfd);return 0;
}
与setsockopt()
相同,getsockopt()
也有许多可用的level
和optname
选项,并且它们的含义与setsockopt()
函数中的相同。不同的操作系统和版本可能会支持不同的选项,所以建议查阅特定操作系统的手册页或其他文档来了解完整的详细信息。
相关文章:

Linux网络编程- struct packet_mreq setsockopt()
struct packet_mreq struct packet_mreq 是一个数据结构,用于 Linux 中的原始数据包套接字,当我们想改变套接字的行为以接收特定类型的数据包时,它与 setsockopt() 函数配合使用。 下面是 struct packet_mreq 的定义: struct p…...

C++学习day4
作业: 1> 思维导图 2> 整理代码 1. 拷贝赋值函数课上代码 //拷贝赋值函数课上代码 #include<iostream> using namespace std;//创建类 class Stu { private://私有的string name;int socer;int *age;//此处注意用到指针类型 public://共有的//无参构…...

从零学算法54
54.给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 螺旋遍历:从左上角开始,按照 向右、向下、向左、向上 的顺序 依次 提取元素,然后再进入内部一层重复相同的步骤,直到…...

Logback日志框架使用详解以及如何Springboot快速集成
Logback简介 日志系统是用于记录程序的运行过程中产生的运行信息、异常信息等,一般有8个级别,从低到高为All < Trace < Debug < Info < Warn < Error < Fatal < OFF off 最高等级,用于关闭所有日志记录fatal 指出每个…...

Nginx概念
Nginx概念 Nginx 是一款面向性能设计的 HTTP 服务器,相较于 Apache、lighttpd 具有占有内存少,稳定性高等优势,同时也是一个非常高效的反向代理、负载平衡服务器 nginx使用的是反应器模式,主事件循环等待操作系统发出准备事件的信…...

vim基础指令(自用)
这个是自己随便写的,类似于笔记 vim 多模式编辑器 查看指令: gg: 定位光标到最开始行 shift(按)g 定位到最结尾行 nshift(按)g 定位到任意行 shift$ 定位到本行结尾 0 定位到本行开头 w:跨单词移动 h.j.k,l: 左下上右 …...

【centos7安装ElasticSearch】
概述 最近工作中有用到ES ,当然少不了自己装一个服务器捣鼓。本文的ElasticSearch 的版本: 7.17.3 一、下载 ElasticSearch 点此下载 下载完成后上传至 Linux 服务器,本文演示放在: /root/ 下,进行解压࿱…...

ElementPlus Switch 开关基础使用
昨天开发用到开关组件 后台返回字段是 can_write 默认是0 or 1 但是Switch 组件绑定的默认值默认是 true or false 直接绑定会导致默认是关闭状态 在页面一加载 值发生变化时 会自己调用 查了文档 需要使用 active-value 和 inactive-value 来指定绑定的数据类型 …...

Spring Boot:自定义注解--annotation
目录 自定义注解的定义和作用范围如何创建自定义注解创建注解接口 如何使用自定义注解进行数据验证创建注解处理器控制器中使用注解 如何为字段添加注解 自定义注解的定义和作用范围 自定义注解可以作用在类、方法、属性、参数、异常、字段或其他注解上。 如何创建自定义注解…...

WIFI频段
问题: 5ghzwifi频段带宽怎么选 智造喵回答: 选择5GHz WiFi频段的带宽取决于你的网络需求和设备兼容性。通常有两种可选的带宽:20MHz和40MHz。 20MHz带宽:这是较为常见的 WiFi 频段带宽设置。它提供较好的穿墙能力和信号稳定性…...

Java的引用详解与示例
引用的作用 在Java中,引用(Reference)是一种重要的概念,它们用于管理对象的生命周期、内存分配和垃圾回收。引用的作用包括以下几个方面: 内存管理:引用帮助Java虚拟机(JVM)管理内存…...

c++视觉处理---霍夫变换
霍夫直线变换的函数 HoughLines 是OpenCV库中用于执行霍夫直线变换的函数。霍夫直线变换用于检测图像中的直线。下面是该函数的基本用法: cv::HoughLines(image, lines, rho, theta, threshold);image: 输入的二值图像,通常是通过边缘检测算法生成的。…...

el-table 边框颜色修改 简单有效!
废话不多说,直接上图 (1)修改前的图如下: 以上是elementUI原组件自带的样式 (2)下面是修改后的边框图如下: 源码如下: <el-table :data"jctableData" border size…...

Zabbix第二部分:基于Proxy分布式部署实现Web监控和Zabbix HA集群的搭建
代理和高可用 一、基于zabbix-proxy的分布式监控1.1 分布式监控的作用1.2 数据流向1.3 构成组件 二、部署zabbix代理服务器Step1 前置准备Step2 设置 zabbix 的下载源,安装 zabbix-proxyStep3 部署数据库并将zabbix相关文件导入Step4 修改zabbix-proxy的配置文件&am…...

JumpServer rce深入剖析
影响范围 JumpServer < v2.6.2 JumpServer < v2.5.4 JumpServer < v2.4.5 JumpServer v1.5.9 修复链接及参考 修改了一处代码: Git History 增加了一处鉴权 def connect(self):user self.scope["user"]if user.is_authenticated and …...

EasyExcel导入/导出Excel文件
EasyExcel导入/导出Excel文件简单写法 1、导入依赖 2、创建简单导入、导出demo 3、创建类 继承AnalysisEventListener(导入Excel监听解析表格数据) 4、创建类 基于注解 自定义Excel导出模版 1、导入EasyExcel依赖 <!--导入EasyExcel…...

力扣(LeetCode)2512. 奖励最顶尖的K名学生(C++)
优先队列哈希集合反向思维(或自定义排序) 模拟,请直接看算法思路: 两个哈希集合S1和S2, S1存正面词汇,S2存负面词汇;一个优先队列pq,pq存{score, id}键值对,即学生分数-学生id。 算法流程: 初…...

CubeMX+BabyOS 使用方法
MCU:STM32G030F 编译器:MDK 托管工具:Sourcetree CubeMX创建工程 BabyOS克隆 添加子模块 git submodule add https://gitee.com/notrynohigh/BabyOS.git BabyOS 切换dev 分支 查看当前分支 git branch -a 切换本地分支到dev git che…...

OpenResty安装-(基于Nginx的高性能Web平台,可在Nginx端编码业务)
文章目录 安装OpenResty1.安装1)安装开发库2)安装OpenResty仓库3)安装OpenResty4)安装opm工具5)目录结构6)配置nginx的环境变量 2.启动和运行3.备注 安装OpenResty 1.安装 首先你的Linux虚拟机必须联网 …...

算法-DFS+记忆化/动态规划-不同路径 II
算法-DFS记忆化/动态规划-不同路径 II 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/unique-paths-ii 1.2 题目描述 2 DFS记忆化 2.1 思路 注意题意,每次要么往右,要么往下走,也就是说不能走回头路。但是仍有可能走到之前已经…...

黑盒测试方法:原理+实战
目录 一、如何设计测试用例 二、黑盒测试常用方法 1、基于需求进行测试用例的设计 2、等价类 3、边界值 4、判定表分析法(因果分析法) 5、正交表 6、场景设计法 三、案例补充 1、使用Fiddler模拟弱网 2、针对一个接口该如何测试 一、如何设计测试…...

SQLite事务处理
语法 BEGIN TRANSACTION; COMMIT TRANSACTION; (或END TRANSACTION;) ROLLBACK TRANSACTION; 事务处理 除了一些PRAGMA语句以外,其它访问数据库的语句会自动启动事务处理,并且在结束时自动提交。 通过上一节的命令可以手动控制…...

Java中CountDownLatch使用场景
在Java的并发API中,CountDownLatch是一个同步器,它允许一个或多个线程等待一组操作完成。 如果您正在开发一个服务器应用程序,该应用程序在开始处理请求之前需要初始化各种资源。这些资源可能是这样的: 加载配置文件建立数据库连…...

漏刻有时数据可视化Echarts组件开发(41)svg格式地图应用
1.定义SVG文件 var svg ;2.注册地图函数 Echarts.registerMap是Echarts图表库中用于注册地图的函数。它可以将第三方地图或自定义地图数据与Echarts进行集成,使用Echarts的API进行绘制。使用方法如下: echarts.registerMap(mapName, geoJson) 参数map…...

firefox的主题文件位置在哪?记录以防遗忘
这篇文章写点轻松的 最近找到了一个自己喜欢的firefox主题,很想把主题的背景图片找到,所以找了下主题文件所在位置 我的firefox版本:版本: 118.0.1 (64 位)主题名称: Sora Kawai 我的位置在 C:\Users\mizuhokaga\AppData\Roaming\Mozilla\Firefox\Profiles\w0e4e24v.default…...

Vuex获取、修改参数值及异步数据处理
14天阅读挑战赛 学不可以已... 目录 一、Vuex简介 1.1 vuex介绍 1.2 vuex核心 二、Vuex使用 2.1 Vuex安装 2.2 创建store模块 2.3 创建vuex的store实例并注册上面引入的各大模块 三、使用Vuex获取、修改值案例 3.1 创建两个菜单组件 3.2 配置路由 3.3 模拟菜单数据 …...

【 OpenGauss源码学习 —— 列存储(autoanalyze)(二)】
列存储(autoanalyze)(二) 概述PgStat_StatTabEntry 结构体pgstat_count_heap_insert 与 pgstat_count_cu_insert 函数CStoreInsert::BatchInsertCommon 函数pgstat_count_cu_update 函数pgstat_count_cu_delete 函数pgstat_count_…...

使用postman 调用 Webservice 接口
1. 先在浏览器地址栏 访问你的webService地址 地址格式: http://127.0.0.1:8092/xxxx/ws(这个自己的决定)/xxxxXccv?wsdl 2. post man POST 访问wwebService接口 地址格式: http://127.0.0.1:8092/xxxx/ws(这个自己的决定)/xxxxXccv <soapenv:Envelope xmlns:soapenv…...

程序员Google插件推荐
文章目录 AdBlock (广告拦截插件)SuperCopy 超级复制Octotree (github增强工具)GitZip for github (github增强工具)JSON-handleSimpleExtManager(管理谷歌插件)OneTab (标签页合并)PostWoman(接口调试)篡改猴 (Tampermonkey)FeHelper(前端助手) AdBlock (广告拦截插件) ☆ 拦截…...

机器学习中常见的监督学习方法和非监督学习方法有哪些。
问题描述:最近面试某些公司算法岗,看到一道简答题,让你举例熟悉的监督学习方法和非监督学习方法。 问题解答: 监督学习方法常见的比较多: 线性回归(Linear Regression): 用于回归问…...