Во всем примере, включая Руководство Биджа, IP-адрес предоставляется в точечной нотации, а затем подается на ::getaddrinfo()
, Эта почта не отвечает на мой вопрос.
После чего addrinfo
struct используется для функций, связанных с сокетами (например, connect()
, bind()
, listen()
). Например:
struct addrinfo hints, *res;
// ... create socket etc.
connect(sockfd, res->ai_addr, res->ai_addrlen);
пример
Переменная ai_addr
имеет тип sockaddr
который может быть безопасно типизированный до sockaddr_storage
, sockaddr_in
а также sockaddr_in6
,
Вопрос:
Если я приведу sockaddr
в sockaddr_in
(или же sockaddr_in6
)
sockaddr_in& ipv4 = (sockaddr_in&)(sockaddr_variable);
и кормить ниже информации:
Могу ли я позвонить connect()
метод, непосредственно использующий вышеупомянутую информацию?
connect(sockfd, &ipv4, sizeof(ipv4));
С моей программой это не работает. Я что-то упустил или есть лучший способ?
Мотивация заключается в том, что если у нас есть информация об IP-адресе, порте и т. Д. В формате, удобном для чтения через сокет, то зачем проходить цикл getaddrinfo()
Убедитесь, что вы размещаете свои значения в сетевом порядке, вот небольшой пример:
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_in server;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
printf("Could not create socket\n");
}
printf("Socket created\n");
server.sin_family = AF_INET;
// 173.194.32.207 is a google address
server.sin_addr.s_addr = 173 | 194 << 8 | 32 << 16 | 207 << 24;
server.sin_port = 0x5000; // port 80
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
{
perror("connect failed. Error");
return 1;
}
printf("Connected\n");
close(sock);
return 0;
}
Сначала проверьте, доступна ли машина & серверное приложение работает на компьютере с помощью утилиты netstat. Используйте метод inet_aton для преобразования точечного адреса в сетевой порядок байтов. Наконец, запишите значение ошибки, возвращенное соединением, чтобы получить точную причину сбоя.
Стоит отметить, что призыв socket::{connect, bind, ...}
это неправильно: это C API
s и C не имеют пространств имен, классов и так далее.
Вы должны использовать getaddrinfo
так как это намного проще и безопаснее в использовании. Но ничто не мешает вам использовать struct sockaddr
и все его варианты. В самом деле, getaddrinfo
является своего рода оберткой, как указано в man(3) getaddrinfo
:
Функция getaddrinfo () объединяет функциональность
предоставляемые функциями gethostbyname (3) и getservbyname (3) в
единый интерфейс, но в отличие от последних функций, getaddrinfo ()
повторно вводить и позволяет программам устранить зависимость IPv4-IPv6
Cies.
Пример:
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
inet_pton(addr.sin_family, "198.252.206.16", &addr.sin_addr);
int fd = socket(addr.sin_family, SOCK_STREAM, 0);
if (fd == -1)
; /* could not create socket */
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
; /* could not connect */
close(fd);
}