You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux环境下Python获取网段/子网掩码的最快实现方法

Linux下Python获取本机CIDR格式网段实现

实现逻辑

要输出192.168.1.0/24格式的CIDR网段,只需要三个步骤:

  • 获取本机实际对外通信的IP地址,避免误拿回环地址
  • 读取该IP对应网卡配置的子网掩码
  • 将子网掩码转换为前缀长度(如255.255.255.0对应前缀24),通过IP和掩码按位与计算出网络地址,拼接成目标格式

纯标准库实现(无第三方依赖)

不需要安装额外包,直接调用Linux系统提供的ioctl接口读取网卡信息即可,代码如下:

import socket
import struct
import fcntl

def get_local_cidr():
    # 获取实际出口IP,规避gethostname绑定回环地址的问题
    conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # 无需真正建立连接,仅触发路由选择拿到出口IP
        conn.connect(('114.114.114.114', 80))
        my_ip = conn.getsockname()[0]
    finally:
        conn.close()

    # 查找IP对应的网卡名称
    def find_target_iface(target_ip):
        for _, iface_name in socket.if_nameindex():
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            try:
                iface_info = fcntl.ioctl(
                    sock.fileno(),
                    0x8915,  # SIOCGIFADDR 常量,用于读取网卡IP
                    struct.pack('256s', iface_name[:15].encode('utf-8'))
                )
                iface_ip = socket.inet_ntoa(iface_info[20:24])
                if iface_ip == target_ip:
                    return iface_name
            except OSError:
                continue
            finally:
                sock.close()
        return None

    target_iface = find_target_iface(my_ip)
    if not target_iface:
        raise RuntimeError("未找到对应IP的网卡设备")

    # 读取对应网卡的子网掩码
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        mask_info = fcntl.ioctl(
            sock.fileno(),
            0x891b,  # SIOCGIFNETMASK 常量,用于读取网卡子网掩码
            struct.pack('256s', target_iface[:15].encode('utf-8'))
        )
        netmask = socket.inet_ntoa(mask_info[20:24])
    finally:
        sock.close()

    # 子网掩码转CIDR前缀长度
    def calc_prefix_len(mask_str):
        return sum(bin(int(segment)).count('1') for segment in mask_str.split('.'))
    prefix_len = calc_prefix_len(netmask)

    # 计算网络地址
    ip_seg = list(map(int, my_ip.split('.')))
    mask_seg = list(map(int, netmask.split('.')))
    network_seg = [str(ip_seg[i] & mask_seg[i]) for i in range(4)]
    network_addr = '.'.join(network_seg)

    return f"{network_addr}/{prefix_len}"

# 调用示例
if __name__ == "__main__":
    print(get_local_cidr())

注意:你之前用的socket.gethostbyname(socket.gethostname())存在兼容性问题,如果系统/etc/hosts里把主机名绑定到127.0.0.1,会错误返回环回地址,上述代码通过UDP socket触发路由选路的方式拿IP,结果更准确。

简化实现(依赖第三方库netifaces)

如果可以安装第三方依赖,用netifaces可以省去手写ioctl调用的逻辑,代码更简洁:

  1. 先安装依赖:
    pip install netifaces
  2. 实现代码:
import socket
import netifaces

def get_local_cidr():
    # 获取出口IP
    conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        conn.connect(('114.114.114.114', 80))
        my_ip = conn.getsockname()[0]
    finally:
        conn.close()

    # 遍历网卡匹配IP,计算CIDR
    for iface in netifaces.interfaces():
        ip_configs = netifaces.ifaddresses(iface).get(netifaces.AF_INET, [])
        for config in ip_configs:
            if config.get('addr') == my_ip:
                netmask = config.get('netmask')
                prefix_len = sum(bin(int(seg)).count('1') for seg in netmask.split('.'))
                ip_seg = list(map(int, my_ip.split('.')))
                mask_seg = list(map(int, netmask.split('.')))
                network_addr = '.'.join([str(ip_seg[i] & mask_seg[i]) for i in range(4)])
                return f"{network_addr}/{prefix_len}"
    raise RuntimeError("获取CIDR网段失败")

内容的提问来源于stack exchange,提问作者Atropin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 01:31:17