我正在尝试使用iOS / Swift下的getpeername()
获取远程IP地址(真实硬件无仿真)。
这就是我正在做的事情:
var addr = sockaddr(sa_len: 0, sa_family: 0, sa_data: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
var len: socklen_t = socklen_t(sizeof(Int32))
if getpeername(socket, &addr, &len) != -1
{
var ipAddressString = [CChar](count:Int(INET_ADDRSTRLEN), repeatedValue: 0)
inet_ntop(
AF_INET ,
&addr,
&ipAddressString,
socklen_t(INET_ADDRSTRLEN))
println("socket \(socket) ip \(String.fromCString(ipAddressString))")
}
我得到的价值是:
socket 7 ip Optional("16.2.209.237")
那肯定不是远程地址。请有人帮帮我吗? 我做错了什么?
答案 0 :(得分:4)
主要错误是inet_ntop()
获取struct in_addr
的地址
(或struct in_addr6
表示IPv6),而不是struct sockaddr
的地址。
另一个错误是getpeername()
的长度参数必须是长度
传递的套接字地址结构,您传递Int32
的长度。
您当前的代码会将AF_INET
传递给inet_ntop()
,因此会受到限制
到IPv4地址。如果这对您来说已经足够,则以下内容应该有效:
var addr = UnsafeMutablePointer<sockaddr_in>.alloc(1)
var len = socklen_t(sizeofValue(addr.memory))
if getpeername(sockfd, UnsafeMutablePointer(addr), &len) != -1 {
var ipAddressString = [CChar](count:Int(INET_ADDRSTRLEN), repeatedValue: 0)
inet_ntop(
AF_INET ,
&addr.memory.sin_addr, // <-- main difference here
&ipAddressString,
socklen_t(INET_ADDRSTRLEN))
println("socket \(sockfd) ip \(String.fromCString(ipAddressString)!)")
}
addr.dealloc(1)
分配套接字地址结构使得在不同指针之间进行转换
类型更容易一点。我还将变量名socket
替换为sockfd
避免与socket()
函数混淆。
更多&#34;现代&#34;将套接字地址转换为字符串的函数是
getnameinfo()
。以下代码演示了如何使用它。它适用于
IPv4和IPv6地址:
var addr = UnsafeMutablePointer<sockaddr_storage>.alloc(1)
var len = socklen_t(sizeofValue(addr.memory))
if getpeername(sockfd, UnsafeMutablePointer(addr), &len) != -1 {
var hostBuffer = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
if (getnameinfo(UnsafeMutablePointer(addr), socklen_t(addr.memory.ss_len),
&hostBuffer, socklen_t(hostBuffer.count), nil, 0,
NI_NUMERICHOST) == 0) {
let host = String.fromCString(hostBuffer)!
println("socket \(sockfd) ip \(host)")
}
}
addr.dealloc(1)
Swift 2更新:第一种方法:
var addr = sockaddr_in()
var len = socklen_t(sizeofValue(addr))
withUnsafeMutablePointer(&addr) {
if getpeername(sockfd, UnsafeMutablePointer($0), &len) != -1 {
var ipAddressString = [CChar](count:Int(INET_ADDRSTRLEN), repeatedValue: 0)
inet_ntop(
AF_INET ,
&addr.sin_addr, // <-- main difference here
&ipAddressString,
socklen_t(INET_ADDRSTRLEN))
print("socket \(sockfd) ip \(String.fromCString(ipAddressString)!)")
}
}
第二种方法:
var addr = sockaddr_storage()
var len = socklen_t(sizeofValue(addr))
withUnsafeMutablePointer(&addr) {
if getpeername(sockfd, UnsafeMutablePointer($0), &len) != -1 {
var hostBuffer = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
if (getnameinfo(UnsafeMutablePointer($0), socklen_t(addr.ss_len),
&hostBuffer, socklen_t(hostBuffer.count), nil, 0,
NI_NUMERICHOST) == 0) {
let host = String.fromCString(hostBuffer)!
print("socket \(sockfd) ip \(host)")
}
}
}
答案 1 :(得分:2)
func getEndpointFromSocketAddress(socketAddressPointer: UnsafePointer<sockaddr>) -> (host: String, port: Int)? {
let socketAddress = UnsafePointer<sockaddr>(socketAddressPointer).memory
switch Int32(socketAddress.sa_family) {
case AF_INET:
var socketAddressInet = UnsafePointer<sockaddr_in>(socketAddressPointer).memory
let length = Int(INET_ADDRSTRLEN) + 2
var buffer = [CChar](count: length, repeatedValue: 0)
let hostCString = inet_ntop(AF_INET, &socketAddressInet.sin_addr, &buffer, socklen_t(length))
let port = Int(UInt16(socketAddressInet.sin_port).byteSwapped)
return (String.fromCString(hostCString)!, port)
case AF_INET6:
var socketAddressInet6 = UnsafePointer<sockaddr_in6>(socketAddressPointer).memory
let length = Int(INET6_ADDRSTRLEN) + 2
var buffer = [CChar](count: length, repeatedValue: 0)
let hostCString = inet_ntop(AF_INET6, &socketAddressInet6.sin6_addr, &buffer, socklen_t(length))
let port = Int(UInt16(socketAddressInet6.sin6_port).byteSwapped)
return (String.fromCString(hostCString)!, port)
default:
return nil
}
}