Получить IP-адрес и номер порта из структуры sockaddr_in в Swift?
После долгих проб и ошибок и без какого-либо успеха, кажется, мне может понадобиться немного помощи в этом:
Как я могу получить IP-адрес и номер порта от sockaddr_in в последней версии Swift?
Я видел некоторые связанные вопросы, но нигде не могу найти подходящий пример. Кроме того, я не совсем понимаю, как нужно обрабатывать структуры и указатели на С-типах в Swift, что не очень помогает.
Может ли кто-нибудь предоставить мне пример или ссылку на полезные ресурсы?
Спасибо заранее!
1 ответ
Если вам нужны IP-адрес и порт в виде чисел, вы можете получить доступ к соответствующим полям sockaddr_in
напрямую, но не забудьте преобразовать значения из сетевого байта (big endian) в порядок байтов хоста:
let saddr: sockAddr = ...
let port = in_port_t(bigEndian: sockAddr.sin_port)
let addr = in_addr_t(bigEndian: sockAddr.sin_addr.s_addr)
getnameinfo()
может использоваться для извлечения IP-адреса в виде строки (в десятичном виде с разделительными точками) и, в качестве опции, порта. Кастинг struct sockaddr_in
указатель на struct sockaddr
в Swift указатель называется "перепривязка" и выполняется с withMemoryRebound()
:
var sockAddr: sockaddr_in = ...
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
var service = [CChar](repeating: 0, count: Int(NI_MAXSERV))
withUnsafePointer(to: &sockAddr) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 0) {
_ = getnameinfo($0, socklen_t($0.pointee.sa_len),
&hostname, socklen_t(hostname.count),
&service, socklen_t(service.count),
NI_NUMERICHOST | NI_NUMERICSERV)
}
}
print("addr:", hostname)
print("port:", service)
Это работает для структур адресов сокетов IPv4 и IPv6 (sockaddr_in
а также sockaddr_in6
).
Для получения дополнительной информации о "небезопасных преобразованиях указателей" см. SE-0107 UnsafeRawPointer API и UnsafeRawPointer Migration. Последняя страница содержит пример кода, как обрабатывать адреса сокетов в Swift 3.