If you need the IP address and port as numbers then you can
access the corresponding fields of a sockaddr_in
directly, but
remember to convert the values from network byte (big endian) to host
byte order:
let saddr: sockAddr = ...
let port = in_port_t(bigEndian: sockAddr.sin_port)
let addr = in_addr_t(bigEndian: sockAddr.sin_addr.s_addr)
getnameinfo()
can be used to extract the IP address as a string
(in dotted-decimal notation), and optionally the port as well.
Casting a struct sockaddr_in
pointer to a struct sockaddr
pointer
is called "rebinding" in Swift, and done with 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)
This works for both IPv4 and IPv6 socket address structures (sockaddr_in
and sockaddr_in6
).
For more information about "unsafe pointer conversions", see
SE-0107 UnsafeRawPointer API
and UnsafeRawPointer Migration. The latter page contains example code how to handle
socket addresses in Swift 3.