Linux网络编程- struct ifreq ioctl() 系统调用

struct ifreq

struct ifreq 是一个数据结构,用于各种与接口相关的输入/输出控制 (ioctl) 调用。它的主要用途是在网络编程中获取和设置网络接口的属性。这个结构体在 <net/if.h> 头文件中定义。

以下是 struct ifreq 的一些主要字段和它们的用途:

  1. ifr_name: 一个字符数组,表示接口的名称,如 “eth0”, “wlan0” 等。

  2. ifr_addr: 一个 struct sockaddr 类型的结构,表示接口的地址。

  3. ifr_netmask: 同样是一个 struct sockaddr 类型的结构,表示接口的网络掩码。

  4. ifr_broadaddr: 表示接口的广播地址。

  5. ifr_flags: 表示接口的标志,如 IFF_UP (接口正在运行)、IFF_BROADCAST (接口支持广播)、IFF_PROMISC (接口在混杂模式下)等。

  6. ifr_hwaddr: 表示接口的硬件(通常是 MAC)地址。

  7. ifr_mtu: 表示接口的最大传输单元 (MTU)。

还有其他一些字段,但上面列出的是最常用的。

当我们想查询或设置接口的特定属性时,会填充 struct ifreq 的适当字段,并使用 ioctl() 系统调用。例如,要设置接口为混杂模式,我们会填充 ifr_name 字段并设置 IFF_PROMISC 标志,然后调用 ioctl()

例如:

struct ifreq ifr;
int sockfd;// 创建一个套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {perror("socket");exit(EXIT_FAILURE);
}// 设置ifr_name为我们想查询或修改的接口名
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);// 获取接口标志
if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {perror("ioctl");close(sockfd);exit(EXIT_FAILURE);
}// 打印是否处于混杂模式
if (ifr.ifr_flags & IFF_PROMISC) {printf("eth0 is in promiscuous mode\n");
} else {printf("eth0 is not in promiscuous mode\n");
}close(sockfd);

这是一个简单的示例,演示了如何检查网络接口(在这种情况下是 “eth0”)是否处于混杂模式。


ioctl() 系统调用

ioctl() 系统调用提供了一种通用的设备驱动程序或接口操作机制,可以用于各种设备特定的操作和控制。它通常用于那些不适合用常规系统调用(如 read(), write(), open() 等)表示的设备特定的操作。

函数原型:

int ioctl(int fd, unsigned long request, ...);

参数:

  1. fd: 是一个已经打开的文件或套接字的文件描述符。

  2. request: 是设备特定的请求码。这个请求码定义了我们想要执行的特定操作或命令。

  3. : 这是一个可变参数,取决于特定的 request。它可能是一个指向数据的指针,也可能是一个直接的值。

返回值:

  • ioctl() 的返回值取决于特定的操作。通常,成功返回非负值,失败返回 -1,并设置 errno

用途:

  1. 网络编程: ioctl() 经常用于查询和设置网络接口的参数。例如,获取或设置接口的 IP 地址,查询或设置接口的标志等。

  2. 设备控制: 对于各种设备(如终端、声音卡、图形卡),ioctl() 可以用于执行特定的操作或查询信息。

  3. 文件系统: 在某些情况下,ioctl() 也可用于文件系统操作。

一些例子:

  1. 获取网络接口的标志:

    struct ifreq ifr;
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);
    ioctl(fd, SIOCGIFFLAGS, &ifr);
    
  2. 设置非阻塞套接字:

    int flags = fcntl(fd, F_GETFL, 0);
    ioctl(fd, FIONBIO, &flags);
    
  3. 查询音频设备属性:

    int volume;
    ioctl(fd, SOUND_MIXER_READ_VOLUME, &volume);
    

注意事项:

  1. 不是所有的设备都支持所有的 ioctl 操作。要知道设备支持哪些操作,需要查阅特定设备的文档或头文件。

  2. 错误处理:与其他系统调用一样,使用 ioctl() 时也应进行适当的错误处理。它可能会失败,并设置 errno,所以应该检查它的返回值并相应地处理错误。

  3. 可移植性ioctl() 是一个非常通用且强大的函数,但它经常与特定的设备或平台相关。这意味着在不同的操作系统或硬件平台上,可能需要不同的 ioctl 请求代码或参数。

总之,ioctl() 提供了一种与设备进行交互的方法,允许开发者执行不同的设备特定操作。然而,正确地使用它需要对特定设备的工作方式有深入的了解。


示例

下面让我们用一个简单的例子来展示如何使用 ioctl() 来获取和设置网络接口(例如 eth0)的 IP 地址。

1. 获取 IP 地址

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <unistd.h>int main() {int sockfd;struct ifreq ifr;// 创建一个 socketsockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("socket");exit(1);}// 指定要查询的接口名strncpy(ifr.ifr_name, "enp5s0", IFNAMSIZ);// 获取接口的 IP 地址if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {perror("ioctl - SIOCGIFADDR ");exit(1);}struct sockaddr_in *ipaddr = (struct sockaddr_in *)&ifr.ifr_addr;printf("IP address of enp5s0: %s\n", inet_ntoa(ipaddr->sin_addr));close(sockfd);return 0;
}

程序运行结果为:

majn@tiger:~/C_Project/network_project$ ./ioctl_setip 
IP address of enp5s0: 192.168.31.6

2. 设置 IP 地址(慎用!!!)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <unistd.h>int main() {int sockfd;struct ifreq ifr;struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;// 创建一个 socketsockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("socket");exit(1);}// 指定要设置的接口名strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);// 设置新的 IP 地址sin->sin_family = AF_INET;inet_aton("192.168.1.100", &sin->sin_addr);if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {perror("ioctl - SIOCSIFADDR ");exit(1);}printf("IP address of eth0 set to: %s\n", inet_ntoa(sin->sin_addr));close(sockfd);return 0;
}

注意: 设置 IP 地址通常需要 root 权限,所以运行上述代码时可能需要使用 sudo

上述示例中,ioctl() 被用来查询或设置网络接口的 IP 地址。具体的操作由 SIOCGIFADDR(获取地址)和 SIOCSIFADDR(设置地址)指定。


inet_aton()

inet_aton() 函数用于将点分十进制格式的字符串(如 “192.168.1.1”)转换为一个网络字节序的 IPv4 地址。它在 <arpa/inet.h> 头文件中定义。

函数原型:

int inet_aton(const char *cp, struct in_addr *inp);

参数:

  • cp: 指向点分十进制格式的 IPv4 地址字符串的指针。
  • inp: 指向一个 struct in_addr 结构体的指针,该结构体用于存储转换后的地址。

返回值:

  • 成功时返回 1,失败时返回 0。

inet_addr() 相比,inet_aton() 函数提供了更清晰的错误检查机制,因为它明确返回成功或失败的状态,而不是使用特殊的地址值来表示错误。

示例:

#include <stdio.h>
#include <arpa/inet.h>int main() {const char *ip_string = "192.168.1.1";struct in_addr ip_addr;if (inet_aton(ip_string, &ip_addr)) {printf("Conversion successful. Network byte order value: 0x%x\n", ip_addr.s_addr);} else {printf("Conversion failed.\n");}return 0;
}

上述程序的运行结果为:

majn@tiger:~/C_Project/network_project$ ./inet_aton_demo 
Conversion successful. Network byte order value: 0x101a8c0

在此示例中,我们将点分十进制的 IP 地址字符串 “192.168.1.1” 使用 inet_aton() 转换为 struct in_addr 格式,并输出转换的结果。

注意:inet_aton()inet_ntoa() 是一对,一个用于将字符串转换为二进制格式,另一个用于进行相反的操作。如果您正在寻找一个线程安全的方法或需要处理 IPv6 地址,建议使用 inet_pton()inet_ntop() 函数代替。


inet_ntoa()

inet_ntoa() 是一个网络工具函数,用于将一个网络字节序的 IPv4 地址转换为点分十进制字符串格式。它在 <arpa/inet.h> 头文件中定义。

函数原型:

char *inet_ntoa(struct in_addr in);

参数:

  • in: 是一个 struct in_addr 结构体,包含一个 IPv4 地址(在网络字节序中)。

返回值:

  • 返回一个指向一个静态分配的字符串的指针,该字符串表示 IPv4 地址的点分十进制表示形式。因为返回的是一个静态字符串,所以之后的 inet_ntoa() 调用可能会覆盖之前的内容。

注意事项:

  1. inet_ntoa() 返回一个指向静态存储区的指针,这意味着每次调用都会覆盖前一次的结果。如果需要保留转换的地址,应该自行复制返回的字符串。
  2. 考虑到线程安全性,inet_ntoa() 在多线程环境中可能会导致问题。为了避免这种情况,可以考虑使用更现代、线程安全的函数,例如 inet_ntop()

示例:

#include <stdio.h>
#include <arpa/inet.h>int main() {struct in_addr ip_addr;ip_addr.s_addr = htonl(0xC0A80101);  // 0xC0A80101 = 192.168.1.1 in hexadecimalchar *ip_str = inet_ntoa(ip_addr);printf("IP address in dotted-decimal format: %s\n", ip_str);return 0;
}

在此示例中,我们创建了一个 struct in_addr 结构体,设置了 IP 地址(以网络字节序),然后使用 inet_ntoa() 将它转换为字符串。

上述程序的运行结果为:

majn@tiger:~/C_Project/network_project$ ./inet_ntoa_demo 
IP address in dotted-decimal format: 192.168.1.1

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

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

相关文章

【生物信息学】使用谱聚类(Spectral Clustering)算法进行聚类分析

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 3. IDE 三、实验内容 0. 导入必要的工具 1. 生成测试数据 2. 绘制初始数据分布图 3. 循环尝试不同的参数组合并计算聚类效果 4. 输出最佳参数组合 5. 绘制最佳聚类结果图 6. 代码整合 一、实验介绍…

HashMap底层源码,数据结构

HashMap的底层结构在jdk1.7中由数组链表实现&#xff0c;在jdk1.8中由数组链表红黑树实现&#xff0c;以数组链表的结构为例。 JDK1.8之前Put方法&#xff1a; JDK1.8之后Put方法&#xff1a; HashMap基于哈希表的Map接口实现&#xff0c;是以key-value存储形式存在&#xff0c…

K8S内容分发网络之集群,nginx,负载均衡,防火墙

K8S内容分发网络之集群&#xff0c;nginx&#xff0c;负载均衡&#xff0c;防火墙 一、Kubernetes 区域可采用 Kubeadm 方式进行安装。1.所有节点&#xff0c;关闭防火墙规则&#xff0c;关闭selinux&#xff0c;关闭swap交换2.修改主机名3.所有节点修改hosts文件4.调整内核参数…

闪击笔试题

选择题 ping命令不涉及什么协议? A&#xff1a;DNS B: TCP C: ARP D: ICMP B&#xff0c;ping基于ICMP协议&#xff0c;解析路由会用到ARP和DNS a、b、c三人参加学科竞赛&#xff0c;每个学科按一二三名次给x、y、z分&#xff0c;已知a得22分&#xff0c;b和c得9分&#xf…

【图论C++】链式前向星(图(树)的存储)

/*** file * author jUicE_g2R(qq:3406291309)————彬(bin-必应)* 一个某双流一大学通信与信息专业大二在读 * * brief 一直在竞赛算法学习的路上* * copyright 2023.9* COPYRIGHT 原创技术笔记&#xff1a;转载需获得博主本人…

人工智能的学习算法

1956年&#xff0c;几个计算机科学家相聚在达特茅斯会议&#xff0c;提出了 “人工智能” 的概念&#xff0c;梦想着用当时刚刚出现的计算机来构造复杂的、拥有与人类智慧同样本质特性的机器。其后&#xff0c;人工智能就一直萦绕于人们的脑海之中&#xff0c;并在科研实验室中…

数组和切⽚ - Go语言从入门到实战

数组和切⽚ - Go语言从入门到实战 数组的声明 package main import "fmt" func main() { var a [3]int //声明并初始化为默认零值 a[0] 1 fmt.Println("a:", a) // 输出: a: [1 0 0] b : [3]int{1, 2, 3} //声明同时初始化 fmt.Println("b:…

Java之多线程综合练习小题一

2. 多线程综合练习 练习一&#xff1a;售票 需求&#xff1a; 一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒, 请用多线程模拟卖票过程并打印剩余电影票的数量 代码示例&#xff1a; public class MyThread extends Thread { ​//第一种方式实现多…

Airtool for Mac——高效便捷的系统菜单栏网络工具!

在我们的数字化生活中&#xff0c;对于网络连接的稳定性和速度有着越来越高的需求。为了满足您对网络质量的实时监测和分析的需求&#xff0c;我们向大家介绍一款强大的Mac系统菜单栏网络工具——Airtool&#xff01; Airtool是一款专为Mac设计的网络工具&#xff0c;它能够提…

Python 笔记07(Mysql数据库基本操作)

一 数据插入 1.1 创建数据列 1.1.1 选择数据库 USE test_data; 1.1.2 插入数据列 ALTER TABLE test_data_info ADD COLUMN stuno INT, ADD COLUMN stuname VARCHAR(255), ADD COLUMN gender VARCHAR(10);1.2 插入具体数据 import MySQLdb# 创建数据库连接 # 主机IP&…

番外5:下载+安装+配置Linux

任务前期工作&#xff1a; 01. 电脑已安装好VMware Workstation软件&#xff1b; 02.提前下载好Rhel-8.iso映像文件&#xff08;文件较大一般在9.4GB&#xff0c;建议采用迅雷下载&#xff09;&#xff0c;本人使用的以下版本&#xff08;地址ed2k://|file|rhel-8.4-x86_64-dvd…

基于PHP+MySQL的养老院管理系统

摘要 随着21世纪互联网时代的兴起&#xff0c;我们见证了人们生活方式的巨大改变。这个时代不仅深刻影响了我们的生活&#xff0c;还改变了我们对信息科学的看法。社会的各个领域都在不断发展&#xff0c;人们的思维也在不断进步&#xff0c;与此同时&#xff0c;信息的需求也与…

rust智能指针

一、智能指针是什么 指针是一个存储内存地址的变量。这个地址指向一些其他数据。 智能指针是一类数据结构&#xff0c;它们类似指针&#xff0c;但是拥有额外的功能。智能指针的概念起源于C。Rust标准库提供了许多智能指针&#xff0c;比如String和Vec<T>&#xff0c;虽…

【React】React组件生命周期以及触发顺序(部分与vue做比较)

最近在学习React&#xff0c;发现其中的生命周期跟Vue有一些共同点&#xff0c;但也有比较明显的区别&#xff0c;并且执行顺序也值得讨论一下&#xff0c;于是总结了一些资料在这里&#xff0c;作为学习记录。 v17.0.1后生命周期图片 初始化阶段 由ReactDOM.render()触发 —…

百度交易中台之内容分润结算系统架构浅析

作者 | 交易中台团队 导读 随着公司内容生态的蓬勃发展&#xff0c;内容产出方和流量提供方最关注的“收益结算”的工作&#xff0c;也就成为重中之重。本文基于内容分润结算业务为入口&#xff0c;介绍了实现过程中的重难点&#xff0c;比如千万级和百万级数据量下的技术选型和…

用Java打印长方形、平行四边形 、三角形、菱形、空心菱形

今天复习使用嵌套for来完成一些任务&#xff0c;于是想着打印一些图形来练习 思考感悟 长方形 行数 和 每行的星星数嵌套遍历即可 平行四边形 核心&#xff1a;每行空格数总行数-行数 行数空格数132231 三角形 核心&#xff1a;每行星星数2*当前行数-1 行数星星数1123…

【VIM】VIm-plug插件

如何查找需要的插件 https://github.com/mhinz/vim-startify https://github.com/vim-airline/vim-airline https://github.com/Yggdroot/indentLine github.com/w0ng/vim-hybrid github.com/altercationi/vim-colors-solarized guithub.com/morhetz/gruvbox github.com/sc…

kotlin aes 加密解密

文章目录 1. key填充2. 加密3. 解密 1. key填充 aes算法对key的字节数有要求 所以对输入的key要做填充处理 fun fillKey(key: String): ByteArray {val random SecureRandom.getInstance("SHA1PRNG")random.setSeed(key.toByteArray())val generator KeyGenerato…

【2023保研】双非上岸东南网安

个人情况 学校&#xff1a;henu 专业&#xff1a;信息安全 排名&#xff1a;1/66 英语&#xff1a;六级500 竞赛&#xff1a;蓝桥杯PB国一&#xff0c;ISCC国一&#xff0c;密码数学挑战赛国三&#xff0c;还有其他一些省级水奖 论文&#xff1a;一篇EI在投&#xff08;三作通…

C++:红黑树

目录 一、关于红黑树 1、红黑树和AVL树区别 2、红黑树规则 二、红黑树 1、红黑树变色举例 2、红黑树具体情况分析 ①、情况一&#xff1a;只变色 ②、情况二&#xff1a;单旋 变色 ③、情况三&#xff1a;双旋 变色 三、红黑树的模拟实现 一、关于红黑树 1、红黑树…