当前位置: 首页 > news >正文

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
};

各字段的详细解释:

  1. mr_ifindex:

    • 这是网络接口的索引号。我们可以使用 if_nametoindex() 函数,将接口名称(如 “eth0”)转换为其索引。(注:if_nametoindex(iface_name) 函数用于将网络接口名称(如 “eth0”)转换为与该接口关联的接口索引。接口索引是内核用于唯一标识网络接口的整数。当 if_nametoindex 函数不能找到指定名称的网络接口时,它会返回0。因此,检查返回值是否为0可以告诉我们是否成功获取了接口索引。)
  2. mr_type:

    • 这是要修改的成员资格类型。例如:
      • PACKET_MR_PROMISC: 设置接口为混杂模式。
      • PACKET_MR_MULTICAST: 加入多播组。
      • PACKET_MR_UNICAST: 添加一个单播地址。
      • PACKET_MR_ALLMULTI: 接收所有多播数据包。
      • PACKET_MR_BROADCAST: 接收所有广播数据包。
  3. mr_alen:

    • 用于指定在 mr_address 字段中的物理地址长度。例如,对于以太网地址,这将是6。
  4. mr_address:

    • 物理层地址。这通常是以太网MAC地址,但长度取决于实际的物理层。例如,当 mr_typePACKET_MR_MULTICAST 时,我们将在此字段中指定要加入的多播地址。

例如,如果想将网络接口 “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_typePACKET_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地址允许网络接口接收发送到该特定多播地址的数据包。这与多播的基本工作方式有关。这里是一个简要的概述:

  1. 多播:多播是在IP网络上向多个接收者发送信息的方法,但不是向所有接收者发送信息(这称为广播)。多播发送的数据包被发送到一个特定的多播IP地址,并由加入该多播组的接收者接收。

  2. 多播MAC地址:由于数据链路层(例如以太网)并不了解IP地址,因此IP多播地址被映射到一个特定的MAC地址范围。这意味着,当一个多播数据包在以太网上发送时,它实际上是发送到一个特定的多播MAC地址。

  3. 加入多播组:如果应用程序对某个多播组感兴趣(即,它想要接收发送到该组的数据包),则需要告诉我们的网络接口加入该组。这样,当接口看到发送到相关多播MAC地址的数据包时,它就知道需要接收它们,而不是忽略它们。

  4. 用途

    • 多播视频和音频流:例如,一个服务器可以将实时视频流发送到多播地址,而所有希望查看该视频流的客户端只需加入相关的多播组即可。
    • 路由协议:一些路由协议使用多播来交换路由信息。
    • 服务发现:一些协议,如mDNS,使用多播来发现网络上的服务。
    • 其他:还有许多其他使用多播的场景,从股票交易到计算机游戏的实时多玩家数据。

总之,通过加入特定的多播MAC地址,我们的网络接口或应用程序可以选择性地接收发送到这些地址的数据包,这对于需要接收特定多播数据的应用程序来说是很有用的。

setsockopt()

setsockopt() 是一个系统调用,用于设置与某个套接字关联的选项。此函数允许应用程序在各种协议级别上设置或更改多种套接字行为。

以下是 setsockopt() 的基本形式:

int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len);

参数解释:

  1. socket:它是要设置选项的套接字的文件描述符。
  2. level:这决定了哪个协议的选项应该被设置。例如,要设置TCP选项,可以使用 IPPROTO_TCP 作为级别。常见的级别包括 SOL_SOCKETIPPROTO_IPIPPROTO_TCP
  3. option_name:这是我们想要设置的具体选项的名称。例如,SO_REUSEADDRSO_KEEPALIVE 都是 SOL_SOCKET 级别的选项。
  4. option_value:这是一个指向要设置选项的新值的指针。
  5. 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:指定的协议级别不识别该选项。
  • EFAULToption_value 指向的内存不是一个有效的部分。

要获取套接字选项的当前值,可以使用 getsockopt() 函数。

注意:具体支持哪些选项和级别可能因操作系统而异,建议查阅特定操作系统的手册页或相关文档以获取详细和完整的信息。


setsockopt()leveloption_name 参数可以取多种值,具体取决于操作系统。以下是一些常见的选项及其解释:

1. level: SOL_SOCKET

这是通用的套接字选项级别。

  • SO_REUSEADDR

    • 说明:允许套接字和其他套接字绑定到相同的地址和端口。这对于在短时间内多次关闭、打开同一地址、端口的服务器应用程序很有用。
  • SO_KEEPALIVE

    • 说明:如果套接字没有接收到数据,在一段时间后将开始发送keepalive消息。这有助于确保连接仍然活动并确定远程主机是否还在线。
  • SO_RCVBUFSO_SNDBUF

    • 说明:设置或获取接收或发送缓冲区的大小。
  • SO_RCVTIMEOSO_SNDTIMEO

    • 说明:设置或获取接收或发送超时。
  • SO_ERROR

    • 说明:获取套接字上的待处理错误。
  • SO_TYPE

    • 说明:获取套接字的类型。

2. level: IPPROTO_IP

这是IP层的选项。

  • IP_TTL

    • 说明:设置或获取Time To Live字段的值。
  • IP_MULTICAST_IF

    • 说明:指定用于发送多播数据报的出口接口。
  • IP_ADD_MEMBERSHIPIP_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()也有许多可用的leveloptname选项,并且它们的含义与setsockopt()函数中的相同。不同的操作系统和版本可能会支持不同的选项,所以建议查阅特定操作系统的手册页或其他文档来了解完整的详细信息。

相关文章:

Linux网络编程- struct packet_mreq setsockopt()

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

C++学习day4

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

从零学算法54

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

Logback日志框架使用详解以及如何Springboot快速集成

Logback简介 日志系统是用于记录程序的运行过程中产生的运行信息、异常信息等&#xff0c;一般有8个级别&#xff0c;从低到高为All < Trace < Debug < Info < Warn < Error < Fatal < OFF off 最高等级&#xff0c;用于关闭所有日志记录fatal 指出每个…...

Nginx概念

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

vim基础指令(自用)

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

【centos7安装ElasticSearch】

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

ElementPlus Switch 开关基础使用

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

Spring Boot:自定义注解--annotation

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

WIFI频段

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

Java的引用详解与示例

引用的作用 在Java中&#xff0c;引用&#xff08;Reference&#xff09;是一种重要的概念&#xff0c;它们用于管理对象的生命周期、内存分配和垃圾回收。引用的作用包括以下几个方面&#xff1a; 内存管理&#xff1a;引用帮助Java虚拟机&#xff08;JVM&#xff09;管理内存…...

c++视觉处理---霍夫变换

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

el-table 边框颜色修改 简单有效!

废话不多说&#xff0c;直接上图 &#xff08;1&#xff09;修改前的图如下&#xff1a; 以上是elementUI原组件自带的样式 &#xff08;2&#xff09;下面是修改后的边框图如下&#xff1a; 源码如下&#xff1a; <el-table :data"jctableData" border size…...

Zabbix第二部分:基于Proxy分布式部署实现Web监控和Zabbix HA集群的搭建

代理和高可用 一、基于zabbix-proxy的分布式监控1.1 分布式监控的作用1.2 数据流向1.3 构成组件 二、部署zabbix代理服务器Step1 前置准备Step2 设置 zabbix 的下载源&#xff0c;安装 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 修复链接及参考 修改了一处代码&#xff1a; Git History 增加了一处鉴权 def connect(self):user self.scope["user"]if user.is_authenticated and …...

EasyExcel导入/导出Excel文件

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

力扣(LeetCode)2512. 奖励最顶尖的K名学生(C++)

优先队列哈希集合反向思维(或自定义排序) 模拟&#xff0c;请直接看算法思路&#xff1a; 两个哈希集合S1和S2, S1存正面词汇&#xff0c;S2存负面词汇&#xff1b;一个优先队列pq&#xff0c;pq存{score, id}键值对&#xff0c;即学生分数-学生id。 算法流程&#xff1a; 初…...

CubeMX+BabyOS 使用方法

MCU&#xff1a;STM32G030F 编译器&#xff1a;MDK 托管工具&#xff1a;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&#xff09;安装开发库2&#xff09;安装OpenResty仓库3&#xff09;安装OpenResty4&#xff09;安装opm工具5&#xff09;目录结构6&#xff09;配置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 思路 注意题意&#xff0c;每次要么往右&#xff0c;要么往下走&#xff0c;也就是说不能走回头路。但是仍有可能走到之前已经…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...