输出错误 inet_ntop
Wrong output inet_ntop
我正在尝试从 inet_ntop 打印一个 IP 地址,但输出看起来很奇怪。
该程序似乎运行良好,我成功连接了套接字,但它打印如下:
H��H9�u�H�[]A\A]A^A_�ff.�
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]){
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct addrinfo hints, *result;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
hints.ai_flags = 0;
int s = getaddrinfo("irc.root-me.org", "6667", &hints, &result);
if( s != 0){
printf("erreur\n");
exit(EXIT_FAILURE);
}
int f = connect(sock, result->ai_addr, result->ai_addrlen);
if(f != 0){
printf("erreur connect\n");
}
struct sockaddr_in *sockin;
sockin = (struct sockaddr_in *)result->ai_addr;
char *dst;
inet_ntop(AF_INET, &sockin->sin_addr, dst, sizeof(char *));
printf("%s\n", dst);
freeaddrinfo(result);
exit(0);
}
这里有两个问题:
inet_ntop()
的 3rd 参数应该是一个 char
数组或指向 1st char
数组的元素。
inet_ntop()
的第4th参数应该是目标缓冲区的size,其地址作为 3rd 参数传递。
你所做的是将未初始化的 char
指针 dst
作为目标传递,并告诉函数它将指向 sizeof(char*)
字节内存。
AF_INET
地址(格式为 xxx.xxx.xxx.xxx
)最多使用 4x3 个字符加上 3 个分隔符 .
char
,总计为 15 char
s 加上 1 个额外的 char
用作 0
-终止符,使其成为 C-"string",因此更正后的代码如下所示:
char dst[16] = ""; /* inet_ntop() does not necessarily 0-terminates the result. */
inet_ntop(AF_INET, &sockin->sin_addr, dst, sizeof dst);
正如 Filipe Gonçalves in 所指出的,可以使用 INET_ADDRSTRLEN
(如果可用)而不是硬编码 "magic number" 16
来定义缓冲区IPv4 地址文本表示的大小。这是好事。
inet_ntop()
的文档在这里:
问题
问题在于您尝试将结果保存到的目标 char* 的大小,以及它未初始化的事实,您要做的是将其保存在 char[] 中。
x86 上的 sizeof(char*) 是 4B,x64 上是 8B,IP 地址通常比它大(IPv4 地址在 7 到 15 字节之间)+ 1 为空终止符。
解决方案
您可以修改代码如下:
char dst[16] = {0};
inet_ntop(AF_INET, &sockin->sin_addr, dst, sizeof(dst));
修复后:
$ ./main
212.83.153.145
源代码
如果你想要完全固定 main.c,我已经 uploaded it to github.
我正在尝试从 inet_ntop 打印一个 IP 地址,但输出看起来很奇怪。
该程序似乎运行良好,我成功连接了套接字,但它打印如下:
H��H9�u�H�[]A\A]A^A_�ff.�
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]){
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct addrinfo hints, *result;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
hints.ai_flags = 0;
int s = getaddrinfo("irc.root-me.org", "6667", &hints, &result);
if( s != 0){
printf("erreur\n");
exit(EXIT_FAILURE);
}
int f = connect(sock, result->ai_addr, result->ai_addrlen);
if(f != 0){
printf("erreur connect\n");
}
struct sockaddr_in *sockin;
sockin = (struct sockaddr_in *)result->ai_addr;
char *dst;
inet_ntop(AF_INET, &sockin->sin_addr, dst, sizeof(char *));
printf("%s\n", dst);
freeaddrinfo(result);
exit(0);
}
这里有两个问题:
inet_ntop()
的 3rd 参数应该是一个char
数组或指向 1stchar
数组的元素。inet_ntop()
的第4th参数应该是目标缓冲区的size,其地址作为 3rd 参数传递。
你所做的是将未初始化的 char
指针 dst
作为目标传递,并告诉函数它将指向 sizeof(char*)
字节内存。
AF_INET
地址(格式为 xxx.xxx.xxx.xxx
)最多使用 4x3 个字符加上 3 个分隔符 .
char
,总计为 15 char
s 加上 1 个额外的 char
用作 0
-终止符,使其成为 C-"string",因此更正后的代码如下所示:
char dst[16] = ""; /* inet_ntop() does not necessarily 0-terminates the result. */
inet_ntop(AF_INET, &sockin->sin_addr, dst, sizeof dst);
正如 Filipe Gonçalves in INET_ADDRSTRLEN
(如果可用)而不是硬编码 "magic number" 16
来定义缓冲区IPv4 地址文本表示的大小。这是好事。
inet_ntop()
的文档在这里:
问题
问题在于您尝试将结果保存到的目标 char* 的大小,以及它未初始化的事实,您要做的是将其保存在 char[] 中。
x86 上的 sizeof(char*) 是 4B,x64 上是 8B,IP 地址通常比它大(IPv4 地址在 7 到 15 字节之间)+ 1 为空终止符。
解决方案
您可以修改代码如下:
char dst[16] = {0};
inet_ntop(AF_INET, &sockin->sin_addr, dst, sizeof(dst));
修复后:
$ ./main
212.83.153.145
源代码
如果你想要完全固定 main.c,我已经 uploaded it to github.