Почему мы можем привести sockaddr к sockaddr_in? - PullRequest
14 голосов
/ 16 февраля 2012

Я понимаю, почему полезно привести sockaddr к sockaddr_in, но я не понимаю, как это возможно. Из того, что я прочитал, они имеют одинаковый размер, и sockaddr_in добавляется с sin_zero, чтобы сделать его одинаковым. Я хотел бы знать, как компилятор знает, где получить информацию от sockaddr_in, если она выложена иначе, чем sockaddr.

1 Ответ

17 голосов
/ 16 февраля 2012

Это возможно, потому что вы обычно используете указатели, а не сами структуры.Вы делаете то, что на естественном языке означает «пожалуйста, вместо этого обращайтесь с этим указателем на socket structure как с указателем на internet socket structure».У компилятора нет проблем с повторной интерпретацией указателя.

Вот более подробное описание, взятое из комментариев:

A sockaddr имеет размер 16 байтов - первые два байта являются sa_family, а оставшиеся 14 байтов являются sa_data, что является произвольными данными.A sockaddr_in также имеет размер 16 байтов - первые 2 байта sin_family (всегда AF_INET), следующие 2 байта sin_port, следующие 4 байта sin_addr (IP-адрес)и последние 8 байтов - это sin_zero, который не используется в IPv4 и предоставляется только для обеспечения 16 байтов.Таким образом, вы можете сначала посмотреть на sockaddr.sa_family, а если это AF_INET, то интерпретировать весь sockaddr как sockaddr_in.

A sockaddr_in не хранится внутри sockaddr.sa_dataполе.Весь sockaddr - это весь sockaddr_in (когда sockaddr.sa_family равен AF_INET, то есть).Если вы возьмете указатель sockaddr* и приведете его к указателю sockaddr_in*, то:

  • sockaddr.sa_family будет sockaddr_in.sin_family
  • байтов 0-1 из sockaddr.sa_datasockaddr_in.sin_port
  • байты 2-5 sockaddr_in.sin_addr
  • байты 6-13 sockaddr_in.sin_zero.
...