4

我正在尝试从 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);
}
4

2 回答 2

7

这里有两个问题:

  1. 第三个参数应该是-array 或指向-array 的一个元素的指针。inet_ntop()charchar

  2. 第 4参数inet_ntop()应该是目标缓冲区的大小,其地址作为第 3 个参数传递。

您所做的是将未初始化的char指针dst作为目标传递,并告诉函数它将指向sizeof(char*)字节内存。

一个AF_INET地址(格式xxx.xxx.xxx.xxx为 )最多使用 4x3 个字符加上 3 个分隔. chars,总和为 15 chars 加上 1 个额外char用作0-terminator 使其成为 C-“字符串”,因此更正后的代码如下所示:

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他的评论中指出的那样,可以使用INET_ADDRSTRLEN(如果可用)而不是硬编码的“幻数”16来定义 IPv4 地址文本表示的缓冲区大小。这是一件好事。


文档在inet_ntop()这里:

于 2015-07-04T15:36:58.097 回答
1

问题

问题在于您尝试保存结果的目标 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,我已将其上传到 github。

于 2015-07-04T15:46:02.830 回答