After much trial and error, and without any success, it seems I might need a bit of help on this one:
How can I get IP address and port number from a sockaddr_in in the latest version of Swift?
I saw some related questions but can't seem to find a proper example anywhere. Also, I don't really seem to grasp how C type structs and pointers need to be handled in Swift, which doesn't really help.
Can anyone please supply me with an example or link to useful resources?
Many thanks in advance!
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.