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()函数中的相同。不同的操作系统和版本可能会支持不同的选项,所以建议查阅特定操作系统的手册页或其他文档来了解完整的详细信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/100718.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zookeeper节点数据类型介绍及集群搭建

一、zookeeper介绍 zookeeper官网&#xff1a;Apache ZooKeeper zookeeper是一个分布式协调框架&#xff0c;保证的是CP&#xff0c;即一致性和分区容错性&#xff1b;zookeeper是一个分布式文件存储系统&#xff0c;文件节点可以存储数据&#xff0c;监听子文件节点等可以实…

docker应用的缓存 docker缓存机制

Docker镜像用作Docker执行程序中的主映像。它们是容器的蓝图&#xff0c;提供了有关如何生成容器的说明。在本文中&#xff0c;我将介绍一些经常被忽视的概念&#xff0c;这些概念将有助于优化Docker镜像开发和构建过程。 让我们从Docker构建过程的简短描述开始。这是通过使用…

艺术字画雕刻经营配送商城小程序的作用是什么

一副传神且精致的绘画/雕塑品不仅具有很好的观赏性&#xff0c;更具备售卖属性&#xff0c;当然由于产品本身本身的局限性&#xff0c;无论开店还是线上朋友圈推广&#xff0c;都难有效果。 通过【雨科】平台搭建字画雕刻经营商城&#xff0c;将所有产品线上售卖&#xff0c;电…

“开启中文智能之旅:探秘超乎想象的 Llama2-Chinese 大模型世界”

“开启中文智能之旅&#xff1a;探秘超乎想象的 Llama2-Chinese 大模型世界” 1.国内Llama2最新下载地址 本仓库中的代码示例主要是基于Hugging Face版本参数进行调用&#xff0c;我们提供了脚本将Meta官网发布的模型参数转换为Hugging Face支持的格式&#xff0c;可以直接通过…

QT CmakeLists配置python

这是exe目录&#xff0c;要放到这里&#xff0c;要放到这里&#xff0c;要放到这里。 find_package(PythonLibs 3.6 REQUIRED) include_directories(${PYTHON_INCLUDE_DIRS})set(PY python/libs/) set(PY_LIBS ${PY}_tkinter ${PY}python3 ${PY}python36 ${PY}python36_d) targ…

排序算法——直接插入排序

一、介绍 插入排序就是将前两个元素排好&#xff0c;再将第三个元素通过与前边的元素比较后插入适当的位置&#xff0c;再将第四个元素插入&#xff0c;不断重复插入与前边元素比较的操作&#xff0c;直到将元素都排列好。 演示如下&#xff1a; 视频演示&#xff1a;…

2731. 移动机器人

2731. 移动机器人有一些机器人分布在一条无限长的数轴上&#xff0c;他们初始坐标用一个下标从 0 开始的整数数组 nums 表示。当你给机器人下达命令时&#xff0c;它们以每秒钟一单位的速度开始移动。 给你一个字符串 s &#xff0c;每个字符按顺序分别表示每个机器人移动的方…

京东数据分析平台:9月中上旬白酒消费市场数据分析

9月份&#xff0c;围绕白酒的热点不断。9月5日&#xff0c;瑞幸咖啡官微发布消息称&#xff0c;瑞幸与贵州茅台跨界合作推出的酱香拿铁刷新单品纪录&#xff0c;首日销量突破542万杯&#xff0c;销售额破1亿元。9月14日&#xff0c;贵州茅台官微发布消息称与德芙推出联名产品“…

软件培训测试高级工程师多测师肖sir__html之作业11

html之作业 案例1&#xff1a; 截图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>表单</title></head><body><table style"background-color:red" bo…

【C++】list基本接口+手撕 list(详解迭代器)

父母就像迭代器&#xff0c;封装了他们的脆弱...... 手撕list目录&#xff1a; 一、list的常用接口及其使用 1.1list 构造函数与增删查改 1.2list 特殊接口 1.3list 排序性能分析 二、list 迭代器实现&#xff08;重点难点&#xff09; 关于迭代器的引入知识&#xff1a…

redis 生成流水工具类

使用redis存储流水号&#xff0c;代码如下&#xff1a; import cn.hutool.core.date.DateUtil; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component;Component public class RedisSerialUtil {private RedisTemplate…

1、网络编程常见协议

1、协议 ​ 传输数据之前需要指定好规则&#xff1a; #mermaid-svg-hfYOuEyyv6poU5a7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-hfYOuEyyv6poU5a7 .error-icon{fill:#552222;}#mermaid-svg-hfYOuEyyv6poU5a7 …

Mac mov转mp4,详细转换步骤

Mac mov转mp4怎么转&#xff1f;视频文件格式为.mov是由Apple公司所开发的特殊格式。因其只能在苹果设备上播放&#xff0c;与他人分享时就会变得困难。为此&#xff0c;我们通常会选择使用MP4这种最受欢迎的视频格式。在日常使用中&#xff0c;MP4成为了大家首选的视频格式。而…

onlyoffice历史版本功能实现

一&#xff1a;开启客户端配置 如果不开启&#xff0c;回调请求里面的history和changeUrl是空 二&#xff1a;客户端主要实现2个回调函数 1.实现onRequestHistory事件&#xff0c;该事件会在ui点击查看历史的时候发起,用于展示历史列表 关键在于获取到history的内容&#xff…

代理IP与Socks5代理在多领域的卓越应用

随着数字化时代的到来&#xff0c;网络工程师在跨界电商、爬虫、出海业务、网络安全和游戏等多个领域中扮演着至关重要的角色。在这些领域中&#xff0c;代理IP与Socks5代理技术已经成为网络工程师的得力助手&#xff0c;本文将深入探讨它们在技术世界中的卓越应用。 1. 跨界电…

写爬虫?前端er何必用python

前言 说起网络爬虫,很多人第一时间想到python,但爬虫并非只能用python实现,虽然网上大部分爬虫文章都在说python爬虫,但对于前端程序员来说,我觉得js才是最屌的(对于简单爬取任务来说,复杂的我暂时没碰到~),下面说说我的经验(是的,仅限本人经验),希望能给各位前…

RPA机器人在电商领域有哪些应用?

随着科技的不断发展&#xff0c;机器人流程自动化&#xff08;RPA&#xff09;已经成为许多领域的重要工具。在电商领域&#xff0c;RPA机器人也发挥了重要的作用。我将从两个方面探讨RPA机器人在电商领域的应用&#xff0c;以及它们如何提高电商运营的效率和效益。 一、RPA机…

Oracle修改数据之后提交事务如何回滚?

在 MySQL 和 Oracle 数据库中&#xff0c;事务提交后都无法回滚。 在 MySQL 中&#xff0c;恢复机制是通过回滚日志&#xff08;undo log&#xff09;实现的&#xff0c;所有事务进行的修改都会先记录到这个回滚日志中&#xff0c;然后在对数据库中的对应行进行写入。当事务已经…

kafka广播消费组停机后未删除优化

背景 kafka广播消息的时候为了保证groupId不重复&#xff0c;再创建的时间采用前缀时间戳的形式&#xff0c;这样可以保证每次启动的时候是创建的新的&#xff0c;但是 会出现一个问题&#xff1a;就是每次停机或者重启都会新建一个应用实例&#xff0c;关闭应用后并不会删除…

Bun v1.0.3 发布,Zig 编写的 JavaScript 运行时

导读Bun 发布了其最新版本 v1.0.3&#xff0c;这是一个集 JavaScript 运行时、打包器、转译器和包管理器于一体的工具。这次的更新不仅修复了众多已知的问题&#xff0c;还引入了一系列令人期待的新功能。 首先&#xff0c;Bun 在这个版本中增加了对 TypeScript 的 emitDecora…