Как скопировать 4 байта в sockaddr.sa_data? - PullRequest
3 голосов
/ 01 августа 2020

Согласно { ссылка }, я могу использовать

std::string ip ="192.168.1.54";
std::stringstream s(ip);
int a,b,c,d; //to store the 4 ints
char ch; //to temporarily store the '.'
s >> a >> ch >> b >> ch >> c >> ch >> d;
std::cout << a << "  " << b << "  " << c << "  "<< d;

для преобразования IP-адреса в его 4 байта. Как мне поместить их в

struct sockaddr
  {
    __SOCKADDR_COMMON (sa_);    /* Common data: address family and length.  */
    char sa_data[14];       /* Address data.  */
  };

?

Должен ли я просто скопировать 4 байта в первые 4 байта sa_data?

Ответы [ 2 ]

7 голосов
/ 01 августа 2020

Фактически вы не используете struct sockaddr напрямую. Вместо этого вы должны заполнить struct sockaddr_in, который предназначен для хранения IPv4-адреса и порта, а затем передать адрес этой структуры функциям, которые ожидают struct sockaddr *.

Чтобы заполнить поле адреса sockaddr_in из строки C вы можете использовать inet_addr.

Например:

struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(ip.c_str());
sin.sin_port = 0;

При вызове recvfrom параметр addrlen должен быть указателем на переменная, которая устанавливается равной размеру структуры, на которую указывает параметр src_addr. Например:

struct sockaddr_in peerAddr;
socklen_t len = sizeof(peerAddr);
recvfrom(sock, data, capacity, 0, (struct sockaddr *)&peerAddr, &len);
5 голосов
/ 01 августа 2020

Лучший способ сделать это - использовать getaddrinfo, что-то вроде

struct addrinfo params = { 0 };
params.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; // adjust
params.ai_family = AF_UNSPEC;
params.ai_socktype = SOCK_STREAM; // adjust
params.ai_protocol = IPPROTO_TCP; // adjust

struct addrinfo *addrs;
int status = getaddrinfo(ip.c_str(), port.c_str(), &params, &addrs);
if (status == EAI_SYSTEM) {
  fprintf(stderr, "%s:%s: %s\n", ip.c_str(), port.c_str(), strerror(errno));
  return -1;
} else if (status) {
  fprintf(stderr, "%s:%s: %s\n", ip.c_str(), port.c_str(), gai_strerror(status));
  return -1;
}
for (struct addrinfo *ai = addrs; ai; ai = ai->ai_next) {
  // do something with ai->ai_addr etc here
}
freeaddrinfo(addrs);
return 0;

. Вам нужно будет отрегулировать строки с пометкой «Adjust» для вашего приложения. Вам также потребуется указать номер порта (что неудобно, он принимает это как строку , потому что он также может принимать имя протокола).

Преимущества этого способа: : Каждая запись в связанном списке addrs содержит все данные, необходимые для создания и подключения сокета к этому адресу; он легко обрабатывает IPv6 за вас; и, если вы уберете AI_NUMERICHOST, он легко обработает доменные имена и для вас.

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