Отличаются ли они: преобразование типа указателя, затем получение данных И получение данных указателя, а затем преобразование типа данных - PullRequest
0 голосов
/ 29 ноября 2018

Я пытаюсь использовать gethostbyname () для TCP-соединения.Я не очень понимаю, почему следующие две строки имеют разные результаты:

sin.sin_addr.s_addr = (uint32_t)(*(hs->h_addr_list[0]));
sin.sin_addr.s_addr = *(uint32_t *)(hs->h_addr_list[0]);

Первая строка получает данные указателя, а затем преобразует тип данных, в то время как вторая строка сначала преобразует тип данных, а затем получаетданные.Мой код показан ниже:

#include "net.h"

int main(int argc, const char *argv[])
{
    int fd = -1;
    struct sockaddr_in sin;

    if ((fd = socket(AF_INET,SOCK_STREAM,0)) < 0)
    {
        perror("socket");
        exit(-1);
    }

    struct hostent * hs;
    if((hs = gethostbyname(SERV_IP_ADDR)) == NULL)
    {
        herror("gethostbyname");
        exit(-1);
    }

    bzero(&sin,sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(SERV_PORT);

    //sin.sin_addr.s_addr = (uint32_t)(*(hs->h_addr_list[0]));
    sin.sin_addr.s_addr = *(uint32_t *)(hs->h_addr_list[0]);

    printf("%d:%d\n",(uint32_t)(*(hs->h_addr_list[0])),*(uint32_t *)(hs //
            ->h_addr_list[0]));
    if(connect(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
    {
        perror("connect");
        exit(-1);
    }

    puts("client OK");

    char buf[BUFSIZ];
    int ret = -1;

    while(1)
    {
        bzero(buf,BUFSIZ);
        if(fgets(buf,BUFSIZ-1,stdin) == NULL)
        {
            continue;
        }
        do{
            ret = write(fd,buf,strlen(buf));
        }while(ret < 0 && errno == EINTR);

        if(strncmp(buf,"quit",strlen("quit")) == 0)
        {
            puts("client exits");
            break;
        }
    }

    close(fd);

    return 0;
}

1 Ответ

0 голосов
/ 29 ноября 2018

h_addr_list - это символ ** в структуре размещения.

Итак:

sin.sin_addr.s_addr = (uint32_t)(*(hs->h_addr_list[0]));

hs-> h_addr_list [0] содержит дает указатель на символ.

Вы разыменовываете его, получая символ, затем бросаете его в uint32_t.Это означает, что вы берете первый байт, на который указывает hs-> h_addr_list [0], и конвертируете его в 4-байтовое целое число, тем самым теряя последующие 3 байта.

You do getчисло в вашем uint32_t, но оно представляет собой однобайтовое целое число.

sin.sin_addr.s_addr = *(uint32_t *)(hs->h_addr_list[0]);

Здесь вы берете указатель char, приводите его к указателю uint32_t и затем разыменовываете его.

Таким образом, вы читаете все 4 байта, начиная с hs-> h_addr_list [0], которые могут быть напрямую преобразованы в ваш uint32_t.Если вы знаете, что ваша структура hs правильно инициализирована, это будет работать.

В качестве предостережения: Полученное значение uint32_t будет иметь сетевой порядковый номер, который может отличаться от порядкового номера вашего компьютера.

Пока функции, которым вы передаете это значение, ожидают этого, хорошо.Вы должны просто осознавать это в глубине души.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...