首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言實現IP地址合法性校驗與子網匹配

     編輯:關於C語言

C語言實現IP地址合法性校驗與子網匹配

在網絡編程中,IP地址合法性判斷、子網掩碼有效性驗證、IP與掩碼組合合法性檢查以及兩個IP是否屬於同一子網,是基礎且高頻的需求。本文提供一套基於標準 socket API 的 C 語言實現,支持 IPv4,代碼可移植至 Linux/Windows 平台。

核心功能函數

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#ifdef _WIN32
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#endif

typedef uint32_t IPAddr;  // 網絡字節序

// 判斷 IP 地址是否合法(排除全0、全1、組播、保留地址等簡化邏輯)
int netIpIsValid(IPAddr ip) {
    struct in_addr addr = { .s_addr = ip };
    // inet_ntoa 返回靜態緩衝區,非線程安全,僅演示用
    const char* str = inet_ntoa(addr);
    IPAddr check = inet_addr(str);
    return (check != INADDR_NONE && check != 0 && check != 0xFFFFFFFF);
}

// 判斷子網掩碼是否合法(必須是連續的1後跟連續的0)
int netMaskIsValid(IPAddr mask) {
    if (!netIpIsValid(mask)) return 0;
    uint32_t hmask = ntohl(mask);
    // 技巧:合法掩碼 hmask | (hmask - 1) == 0xFFFFFFFF
    return ((hmask | (hmask - 1)) == 0xFFFFFFFF);
}

// 判斷 IP 與掩碼組合是否合法(排除網絡地址、廣播地址、子網號全0/全1等)
int netMaskAndIpIsValid(IPAddr ip, IPAddr mask) {
    if (!netIpIsValid(ip) || !netMaskIsValid(mask)) return 0;
    
    uint32_t hip = ntohl(ip);
    uint32_t hmask = ntohl(mask);
    uint32_t hostPart = hip & ~hmask;
    
    // 主機部分全0(網絡地址)或全1(廣播地址)非法
    if (hostPart == 0 || hostPart == ~hmask) return 0;
    
    // 簡化的 A/B/C 類默認掩碼檢查(實際應用中 CIDR 無類別,此邏輯僅作演示)
    uint8_t firstOctet = hip >> 24;
    if (firstOctet < 128) {        // A類
        if (hmask < 0xFF000000) return 0;
    } else if (firstOctet < 192) { // B類
        if (hmask < 0xFFFF0000) return 0;
    } else if (firstOctet < 224) { // C類
        if (hmask < 0xFFFFFF00) return 0;
    } else return 0; // D/E 類不作為主機地址
    
    // 子網號非全0/全1(RFC 1009 老規範,現代 CIDR 已廢棄,保留兼容)
    uint32_t subnetPart = hip & hmask;
    if (subnetPart == 0 || subnetPart == hmask) return 0;
    
    return 1;
}

// 判斷兩個 IP 是否在同一子網(給定掩碼)
int netIPAndSubnetValid(IPAddr ip1, IPAddr ip2, IPAddr mask) {
    if (!netMaskAndIpIsValid(ip1, mask) || !netMaskAndIpIsValid(ip2, mask)) return 0;
    return (ip1 & mask) == (ip2 & mask);
}

測試用例與說明

int main() {
    // 測試數據:網絡字節序(大端)
    IPAddr ip1 = inet_addr("192.168.10.65");   // 0x410AA8C0
    IPAddr mask1 = inet_addr("255.255.255.192"); // 0xC0FFFFFF
    
    printf("IP: %s, Mask: %s -> %s\n", 
           inet_ntoa(*(struct in_addr*)&ip1),
           inet_ntoa(*(struct in_addr*)&mask1),
           netMaskAndIpIsValid(ip1, mask1) ? "Valid" : "Invalid");
    
    // 同子網測試
    IPAddr ipA = inet_addr("192.168.1.10");
    IPAddr ipB = inet_addr("192.168.1.20");
    IPAddr mask = inet_addr("255.255.255.0");
    printf("Same subnet: %s\n", netIPAndSubnetValid(ipA, ipB, mask) ? "Yes" : "No");
    
    return 0;
}

關鍵技術點解析

  1. 網絡字節序處理:所有 IP/掩碼參數均為網絡序(大端)。使用 htonl/ntohl、htons/ntohs、inet_addr/inet_ntoa 進行轉換。注意 inet_ntoa 返回靜態緩衝區,多線程環境下需用 inet_ntop。
  2. 掩碼合法性判斷:利用位運算技巧 (mask | (mask-1)) == 0xFFFFFFFF 判斷是否為連續 1 後跟連續 0。
  3. 保留地址排除:主機位全 0(網絡地址)、全 1(廣播地址)不可分配給主機。
  4. 跨平台兼容:通過宏區分 Windows/Linux 頭文件與庫鏈接。
  5. 編碼規範:布爾函數返回 0/1,調用處直接用 if (func()) 而非 if (func() == TRUE)。

擴展建議

  • 生產環境建議使用 inet_pton/inet_ntop 替代舊 API,支持 IPv6 且線程安全。
  • 引入 CIDR 無類別域間路由邏輯,移除 A/B/C 類默認掩碼硬編碼判斷。
  • 封裝為 C++ 類或提供線程安全版本(避免靜態緩衝區)。

這套代碼涵蓋了 IPv4 地址校驗的核心邏輯,可直接集成到網絡設備配置、防火牆規則解析、SDN 控制器等項目中。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved