我编写了一个服务器,用于侦听传入tcp连接的特定端口。为了管理网络连接,我正在使用Streams(CFStream / NSStream)。在建立连接时,我将有关此连接的所有信息保存在专用类的另一个实例中,该专用类也被设置为流的委托。
现在我想获得通过已经建立的流向我发送消息的设备的公共IP,换句话说,我想存储流的对等体的IP。我尝试了很多东西,但遗憾的是我只获得了空值。
是否有可能从所描述表单的现有流中获取对等方的地址(ip和端口)?
以下是我尝试过的一些代码:
CFDataRef peerAddress = CFSocketCopyPeerAddress(_sockRef);
// _sockRef is saved when connection is established in listening callback and is not null
我还尝试直接在侦听回调方法中获取信息:
NSData *peer = nil;
CFSocketNativeHandle nativeSocketHandle = *(CFSocketNativeHandle *)data;
struct sockaddr *addressinfo = NULL;
uint8_t name[SOCK_MAXADDRLEN];
socklen_t namelen = sizeof(addressinfo);
int result = getpeername(nativeSocketHandle, addressinfo, &namelen);
if (result == 0) {
peer = [NSData dataWithBytes:name length:namelen];
}
struct sockaddr_in *s = (struct sockaddr_in*)name;
char *ipstr = malloc(INET_ADDRSTRLEN);
ipstr = inet_ntoa(s->sin_addr); // is 0.0.0.0 :-(
我尝试了另一种方法:
_publicIP = CFWriteStreamCopyProperty((__bridge CFWriteStreamRef)(_writeStream), kCFStreamPropertySocketRemoteHostName);
为什么我总是得到空值?任何人都可以帮助我吗?
提前谢谢!
答案 0 :(得分:4)
好的,我现在想通了。这就是我所做的:
- (void)getPublicClientAddress {
// Get public IP from stream
// Get hands on appropriate data structures via the socket number
CFSocketNativeHandle nativeSocketHandle = _socketnumber;
uint8_t name[SOCK_MAXADDRLEN];
socklen_t namelen = sizeof(name);
NSData *peer = nil;
if (0 == getpeername(nativeSocketHandle, (struct sockaddr *)name, &namelen)) {
peer = [NSData dataWithBytes:name length:namelen];
}
if (_ipv6){
// If ipv6 is used
struct sockaddr_in6 *socketaddress = (struct sockaddr_in6*)name;
// convert ip to string
char *ipstr = malloc(INET6_ADDRSTRLEN);
struct in6_addr *ipv6addr = &socketaddress->sin6_addr;
inet_ntop(AF_INET6, ipv6addr, ipstr, sizeof(ipstr));
// convert port to int
int portnumber = socketaddress->sin6_port;
// Save in properties
_publicIP = [NSString stringWithFormat:@"%s", ipstr];
_publicPort = [NSString stringWithFormat:@"%d", portnumber];
} else {
// If ipv4 is used
struct sockaddr_in *socketaddress = (struct sockaddr_in*)name;
// convert ip to string
char *ipstr = malloc(INET_ADDRSTRLEN);
struct in_addr *ipv4addr = &socketaddress->sin_addr;
ipstr = inet_ntoa(*ipv4addr);
//inet_ntop(AF_INET, ipv4addr, ipstr, sizeof(ipstr));
// convert port to int
int portnumber = socketaddress->sin_port;
// Save in properties
_publicIP = [NSString stringWithFormat:@"%s", ipstr];
_publicPort = [NSString stringWithFormat:@"%d", portnumber];
}
}
之后,您将拥有属性_publicIP
中的公共IP和属性_publicPort
中的公共端口。所有信息都是从服务器端的连接中收集的。
我希望这篇文章可以帮助某人=)