Linux C/C++ 网络编程中地址格式转换(inet_pton和inet_ntop函数)

简介: Linux C/C++ 网络编程中地址格式转换(inet_pton和inet_ntop函数)

网络编程中地址格式转换(inet_pton和inet_ntop函数)

地址格式转换

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int  inet_pton(int  af ,  const  char  * src  ,void   *  dst);

(1)功能:将点分十进制格式的地址字符串转换为网络字节序整型数

(2)返回值:成功返回1,错误返回-1

(3)参数:

----af   :转换格式 AF_INET(IPV4)或者AF_INET6(IPV6)
    ---- src :点分格式的地址
     ----- dst:转换后的整型变量的地址
const char *  inet_ntop(int  af , const  void  * src ,  char * dst , socklen_t   cnt);

(1)功能:将网络字节序整型数转换为点分格式的IP地址

(2)返回值:成功返回转换后的地址,错误返回NULL

(3)参数:

----af   :转换格式 AF_INET(IPV4)或者AF_INET6(IPV6)
    ---- src :整型变量的地址
     ----- dst:用来存储转换后的数据的地址
    ------cnt:存储空间的大小

错误处理

在使用 inet_ptoninet_ntop 函数时,可能会出现一些错误。为了确保程序的稳定性,我们需要对这些错误进行适当的处理。通常情况下,我们可以使用 perror 函数来打印出具体的错误信息。下面我们将详细介绍如何处理这两个函数的错误,并给出一个错误处理的例子。

首先,我们需要注意 inet_pton 函数的返回值。当成功将地址字符串转换为网络字节序整数时,它会返回 1;如果输入的地址字符串无效,它会返回 0;发生错误时,它会返回 -1。因此,在调用 inet_pton 后,我们需要检查返回值,以确定是否发生了错误。如果返回值为 -1,我们可以使用 perror 函数打印出具体的错误信息。

同样地,对于 inet_ntop 函数,当成功将网络字节序整数转换为点分格式的 IP 地址时,它会返回转换后的地址;如果发生错误,它会返回 NULL。因此,在调用 inet_ntop 后,我们需要检查返回值,以确定是否发生了错误。如果返回值为 NULL,我们可以使用 perror 函数打印出具体的错误信息。

下面是一个处理错误的示例:

#include <stdio.h>
#include <stdlib.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <arpa/inet.h>  
#include <string.h>  
#include <netdb.h>  
int main()  
{  
    int addrnum;  
    char addrstring[] = "Invalid IP address";  
    printf("Address in dotted-quad format is %s\\n", addrstring);  
    if (inet_pton(AF_INET, addrstring, &addrnum) == -1) {
        perror("inet_pton");
        exit(EXIT_FAILURE);
    }
    char addrstring2[16] = "";
    if (inet_ntop(AF_INET, &addrnum, addrstring2, 16) == NULL) {
        perror("inet_ntop");
        exit(EXIT_FAILURE);
    }
    printf("Address in dotted-quad format is %s\\n", addrstring2);  
    return 0;  
}

运行结果:

  1. Address in dotted-quad format is Invalid IP address
  2. inet_pton: Invalid argument

在上面的示例中,我们使用了一个无效的 IP 地址字符串。当调用 inet_pton 函数时,它会返回 -1,表示发生了错误。我们使用 perror 函数打印出错误信息 “Invalid argument”,这表明输入的地址字符串无效。通过这种方式,我们可以轻松地处理 inet_ptoninet_ntop 函数的错误,并确保程序的稳定性。

示例

IPV4

#include <stdio.h>
#include <stdlib.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <arpa/inet.h>  
#include <string.h>  
#include <netdb.h>  
int main()  
{  
  int addrnum;  
    char addrstring[16] = "127.0.0.1";  
    printf("address in dotted-quad format is %s\\n",addrstring);  
    inet_pton(AF_INET,addrstring,&addrnum);  
    printf("address in network byteorder integer is 0x%x\\n",addrnum);  
    char addrstring2[16] = "";  
    if(inet_ntop(AF_INET,&addrnum,addrstring2,16) == NULL)  
      {  
               perror("inet_ntop");  
       }  
      printf("address in dotted - quad format is %s \\n",addrstring2);  
        return 0;  
 }     

运行结果:

[root@rac2 ~]# ./addrformat

  1. address in dotted-quad format is 127.0.0.1
  2. address in network byteorder integer is 0x100007f
  3. address in dotted - quad format is 127.0.0.1

IPV6

#include <stdio.h>
#include <stdlib.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <arpa/inet.h>  
#include <string.h>  
#include <netdb.h>  
int main()  
{  
    int addrnum;  
    char addrstring[INET6_ADDRSTRLEN] = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";  
    printf("IPv6 address in hexadecimal notation is %s\\n", addrstring);  
    struct in6_addr addrnum6;
    if (inet_pton(AF_INET6, addrstring, &addrnum6) != 1) {
        perror("inet_pton");
        exit(EXIT_FAILURE);
    }
    char addrstring2[INET6_ADDRSTRLEN] = "";
    if (inet_ntop(AF_INET6, &addrnum6, addrstring2, INET6_ADDRSTRLEN) == NULL) {
        perror("inet_ntop");
        exit(EXIT_FAILURE);
    }
    printf("IPv6 address in hexadecimal notation is %s\\n", addrstring2);  
    return 0;  
}

在C++ 中的使用示例

在 C++ 中,我们可以使用 RAII(Resource Acquisition Is Initialization)技术和异常处理机制来优雅地使用 inet_ptoninet_ntop 函数。下面是一个综合示例,包含注释和异常捕获:

#include <iostream>
#include <stdexcept>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cstring>
class IPAddress
{
public:
    IPAddress(const std::string& address, int family)
        : family_(family)
    {
        if (family == AF_INET) {
            if (inet_pton(AF_INET, address.c_str(), &addr_.ipv4) != 1) {
                throw std::runtime_error("Invalid IPv4 address: " + address);
            }
        }
        else if (family == AF_INET6) {
            if (inet_pton(AF_INET6, address.c_str(), &addr_.ipv6) != 1) {
                throw std::runtime_error("Invalid IPv6 address: " + address);
            }
        }
        else {
            throw std::runtime_error("Invalid address family");
        }
    }
    std::string toString() const
    {
        char buffer[INET6_ADDRSTRLEN];
        const char* result = inet_ntop(family_, &addr_, buffer, sizeof(buffer));
        if (result == nullptr) {
            throw std::runtime_error("Address conversion failed");
        }
        return std::string(buffer);
    }
private:
    union {
        struct in_addr ipv4;
        struct in6_addr ipv6;
    } addr_;
    int family_;
};
int main()
{
    try {
        // IPv4 示例
        IPAddress ipv4("192.168.1.1", AF_INET);
        std::cout << "IPv4 address: " << ipv4.toString() << std::endl;
        // IPv6 示例
        IPAddress ipv6("2001:0db8:85a3:0000:0000:8a2e:0370:7334", AF_INET6);
        std::cout << "IPv6 address: " << ipv6.toString() << std::endl;
    }
    catch (const std::runtime_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}

应用场景

地址转换在网络编程中具有广泛的应用场景。它的主要作用是在不同表示格式之间进行转换,以便于在各种网络通信和地址解析任务中使用。下面我们将简要介绍地址转换在实际应用场景中的一些用途。

  1. 网络通信:在网络编程中,我们需要与不同的网络设备进行通信。设备之间的通信通常使用网络字节序(大端字节序)表示的整数进行。而人们在日常使用中,通常使用点分十进制(IPv4)或者冒分十六进制(IPv6)表示的 IP 地址。因此,在实际编程过程中,我们需要将人类可读的地址转换为网络字节序整数,或者将网络字节序整数转换为人类可读的地址。这就需要使用 inet_ptoninet_ntop 等地址转换函数。
  2. 地址解析:在许多网络应用中,我们需要根据域名来获取 IP 地址。这个过程通常涉及到 DNS 查询,返回的 IP 地址通常以网络字节序整数的形式表示。为了方便展示和使用,我们需要将这些整数地址转换为点分十进制或冒分十六进制表示的字符串。这时,inet_ntop 函数就派上了用场。
  3. 跨平台兼容性:不同的计算机系统和网络设备可能使用不同的字节序。为了确保跨平台的兼容性,网络通信通常采用网络字节序(大端字节序)表示整数。地址转换函数如 inet_ptoninet_ntop 能够确保在不同平台之间进行正确的转换,从而提高了跨平台应用的兼容性。
  4. 网络诊断与调试:在网络诊断和调试过程中,我们需要处理各种地址信息。地址转换函数可以帮助我们将不同格式的地址信息转换为可读的形式,便于分析和排查问题。

通过以上介绍,我们可以看到地址转换在实际网络编程场景中具有重要的作用。掌握 inet_ptoninet_ntop 等地址转换函数的使用,能够帮助我们更加高效地处理网络通信和地址解析等任务。


目录
相关文章
|
5月前
|
监控 Linux 测试技术
C++零拷贝网络编程实战:从理论到生产环境的性能优化之路
🌟 蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕C++与零拷贝网络编程,从sendfile到DPDK,实战优化服务器性能,毫秒级响应、CPU降60%。分享架构思维,共探代码星辰大海!
|
8月前
|
C++
基于Reactor模型的高性能网络库之地址篇
这段代码定义了一个 InetAddress 类,是 C++ 网络编程中用于封装 IPv4 地址和端口的常见做法。该类的主要作用是方便地表示和操作一个网络地址(IP + 端口)
358 58
|
8月前
基于Reactor模式的高性能网络库github地址
https://github.com/zyi30/reactor-net.git
200 0
|
12月前
|
运维 监控 算法
解读 C++ 助力的局域网监控电脑网络连接算法
本文探讨了使用C++语言实现局域网监控电脑中网络连接监控的算法。通过将局域网的拓扑结构建模为图(Graph)数据结构,每台电脑作为顶点,网络连接作为边,可高效管理与监控动态变化的网络连接。文章展示了基于深度优先搜索(DFS)的连通性检测算法,用于判断两节点间是否存在路径,助力故障排查与流量优化。C++的高效性能结合图算法,为保障网络秩序与信息安全提供了坚实基础,未来可进一步优化以应对无线网络等新挑战。
|
存储 Linux C语言
Linux C/C++之IO多路复用(aio)
这篇文章介绍了Linux中IO多路复用技术epoll和异步IO技术aio的区别、执行过程、编程模型以及具体的编程实现方式。
780 1
Linux C/C++之IO多路复用(aio)
|
9月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
233 0
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
741 6
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
349 16
|
存储 缓存 网络协议
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。