函数 | 功能 | 头文件(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
#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. */
};
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);
}