IP地址转换总结对比

2 分钟读完

##函数对比

函数 功能 头文件(Linux) 原型 源码实现
inet_ntop convert IPv4 and IPv6 addresses from binary to text form arpa/inet.h const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); here
inet_ntoa converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation. The string is returned in a statically allocated buffer, which subsequent calls will overwrite. arpa/inet.h char *inet_ntoa(struct in_addr in); here
inet_addr converts the Internet host address cp from IPv4 numbers-and-dots notation into binary data in network byte order. arpa/inet.h in_addr_t inet_addr(const char *cp); 封装了inet_ntoa
inet_pton convert IPv4 and IPv6 addresses from text to binary form arpa/inet.h int inet_pton(int af, const char *src, void *dst); here
inet_aton converts the Internet host address cp from the IPv4 numbers-and-dots notation into binary form (in network byte order) and stores it in the structure that inp points to. arpa/inet.h int inet_aton(const char *cp, struct in_addr *inp);  

inet_ntoa() 在内部使用了static 数组存储IP,有两个问题:

1.在一个语句中两次以上调用 inet_ntoa ,会输出同样的IP地址,如: printf(“src=%s, dst=%s\n”, inet_ntoa(src), inet_ntoa(dst));

2.经常出现段错误

推荐使用inet_pton/inet_ntop

##网络地址sockaddr_in

	#include <netinet/in.h>
	   
	struct sockaddr_in {
		short            sin_family;   	
		unsigned short   sin_port; 	
		struct in_addr   sin_addr;     	
		char             sin_zero[8];  // 填充对齐
	};
	
	typedef uint32_t in_addr_t;

    struct in_addr {
        in_addr_t s_addr;
    };

	struct sockaddr {
           sa_family_t sa_family;
           char        sa_data[14];
       };

sockaddr 的作用?

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
The only purpose of sockaddr is to cast the structure pointer passed in addr in order to avoid compiler warnings.

bind()作为一个标准接口,不仅接受Network socket address参数,还有下面两种,传参时避免编译警告。

  • 用于进程间通信的 UNIX socket address 结构是

    	struct sockaddr_un {
      sa_family_t sun_family;               /* AF_UNIX */
      char        sun_path[108];            /* pathname */
    };
    

示例: https://goo.gl/XpBgoh

  • 用于内核与用户空间通信的Netlink socket address结构是

    struct sockaddr_nl {
      sa_family_t     nl_family;  /* AF_NETLINK */
      unsigned short  nl_pad;     /* Zero. */
      pid_t           nl_pid;     /* Port ID. */
      __u32           nl_groups;  /* Multicast groups mask. */
    };
    

##示例程序

  • inet_aton
    struct sockaddr_in myaddr;
    int s;
    
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(3490);
    inet_aton("63.161.169.137", &myaddr.sin_addr.s_addr);
    
    s = socket(PF_INET, SOCK_STREAM, 0);
    bind(s, (struct sockaddr*)myaddr, sizeof(myaddr));
  • inet_ntoa

     #define _BSD_SOURCE
     #include <arpa/inet.h>
     #include <stdio.h>
     #include <stdlib.h>
    
     int
     main(int argc, char *argv[])
     {
         struct in_addr addr;
    
         if (argc != 2) {
             fprintf(stderr, "%s <dotted-address>\n", argv[0]);
             exit(EXIT_FAILURE);
         }
    
         if (inet_aton(argv[1], &addr) == 0) {
             fprintf(stderr, "Invalid address\n");
             exit(EXIT_FAILURE);
         }
    
         printf("%s\n", inet_ntoa(addr));
         exit(EXIT_SUCCESS);
     }
    
  • inet_ntop & inet_pton

     #include <arpa/inet.h>
     #include <stdio.h>
     #include <stdlib.h>
     #include <string.h>
    
     int
     main(int argc, char *argv[])
     {
         unsigned char buf[sizeof(struct in6_addr)];
         int domain, s;
         char str[INET6_ADDRSTRLEN];
    
         if (argc != 3) {
             fprintf(stderr, "Usage: %s {i4|i6|<num>} string\n", argv[0]);
             exit(EXIT_FAILURE);
         }
    
         domain = (strcmp(argv[1], "i4") == 0) ? AF_INET :
                  (strcmp(argv[1], "i6") == 0) ? AF_INET6 : atoi(argv[1]);
    
         s = inet_pton(domain, argv[2], buf);
         if (s <= 0) {
             if (s == 0)
                 fprintf(stderr, "Not in presentation format");
             else
                 perror("inet_pton");
             exit(EXIT_FAILURE);
         }
    
         if (inet_ntop(domain, buf, str, INET6_ADDRSTRLEN) == NULL) {
             perror("inet_ntop");
             exit(EXIT_FAILURE);
         }
    
         printf("%s\n", str);
    
         exit(EXIT_SUCCESS);
     }
    

##参考

  • man7.org

留下评论