请原谅我的iPhone / Objective-C新手状态!
我发现我的HTTP服务器使用NSNetServiceBrowser,但现在我只想找到服务的IP地址和端口。
我的委托方法中有以下内容:
NSNetService* server = [serverBrowser.servers objectAtIndex:0];
NSString *name = nil;
NSData *address = nil;
struct sockaddr_in *socketAddress = nil;
NSString *ipString = nil;
int port;
uint i;
for (i = 0; i < [[server addresses] count]; i++)
{
name = [server name];
address = [[server addresses] objectAtIndex:i];
socketAddress = (struct sockaddr_in *)
[address bytes];
ipString = [NSString stringWithFormat: @"%s",
inet_ntoa (socketAddress->sin_addr)];
port = socketAddress->sin_port;
NSLog(@"Server found is %s %d",ipString,port);
}
但是永远不会输入for循环,即使调用了委托。有任何想法吗?谢谢!
答案 0 :(得分:41)
我意识到这是一个老线程,但我也遇到了这个问题。上面的代码存在一些问题:
这不是IPv6精明。在一个 最小,它应该检测和 如果剩下的话,丢弃IPv6地址 您的应用只能处理v4 地址,但理想情况下你应该 准备通过这两个地址 上游家庭。
端口分配将
为英特尔生成错误的值
处理器。您需要使用htons
解决这个问题。
正如安德鲁上面提到的那样 迭代应该使用增强 for loop。
(编辑:已添加此内容)正如另一个相关主题所述,不鼓励使用inet_ntoa
以支持inet_ntop
。
将所有这些放在一起,你得到:
char addressBuffer[INET6_ADDRSTRLEN];
for (NSData *data in self.addresses)
{
memset(addressBuffer, 0, INET6_ADDRSTRLEN);
typedef union {
struct sockaddr sa;
struct sockaddr_in ipv4;
struct sockaddr_in6 ipv6;
} ip_socket_address;
ip_socket_address *socketAddress = (ip_socket_address *)[data bytes];
if (socketAddress && (socketAddress->sa.sa_family == AF_INET || socketAddress->sa.sa_family == AF_INET6))
{
const char *addressStr = inet_ntop(
socketAddress->sa.sa_family,
(socketAddress->sa.sa_family == AF_INET ? (void *)&(socketAddress->ipv4.sin_addr) : (void *)&(socketAddress->ipv6.sin6_addr)),
addressBuffer,
sizeof(addressBuffer));
int port = ntohs(socketAddress->sa.sa_family == AF_INET ? socketAddress->ipv4.sin_port : socketAddress->ipv6.sin6_port);
if (addressStr && port)
{
NSLog(@"Found service at %s:%d", addressStr, port);
}
}
}
答案 1 :(得分:18)
您在回调中返回的NSNetService尚未准备好使用。您必须调用以下方法来获取它的地址:
- (void)resolveWithTimeout:(NSTimeInterval)timeout;
实现NSNetService委托方法以找出它何时解析:
- (void)netServiceDidResolveAddress:(NSNetService *)sender;
此时,服务中至少应有一个地址。
另外,请仔细阅读文档和头文件!这个问题有一些复杂性,我已经掩饰了。
答案 2 :(得分:3)
重新分类接受的答案:
#import <Foundation/Foundation.h>
@interface NSNetService (Util)
- (NSArray*) addressesAndPorts;
@end
@interface AddressAndPort : NSObject
@property (nonatomic, assign) int port;
@property (nonatomic, strong) NSString *address;
@end
#import "NSNetService+Util.h"
#include <arpa/inet.h>
@implementation NSNetService (Util)
- (NSArray*) addressesAndPorts {
// this came from http://stackoverflow.com/a/4976808/8047
NSMutableArray *retVal = [NSMutableArray array];
char addressBuffer[INET6_ADDRSTRLEN];
for (NSData *data in self.addresses)
{
memset(addressBuffer, 0, INET6_ADDRSTRLEN);
typedef union {
struct sockaddr sa;
struct sockaddr_in ipv4;
struct sockaddr_in6 ipv6;
} ip_socket_address;
ip_socket_address *socketAddress = (ip_socket_address *)[data bytes];
if (socketAddress && (socketAddress->sa.sa_family == AF_INET || socketAddress->sa.sa_family == AF_INET6))
{
const char *addressStr = inet_ntop(
socketAddress->sa.sa_family,
(socketAddress->sa.sa_family == AF_INET ? (void *)&(socketAddress->ipv4.sin_addr) : (void *)&(socketAddress->ipv6.sin6_addr)),
addressBuffer,
sizeof(addressBuffer));
int port = ntohs(socketAddress->sa.sa_family == AF_INET ? socketAddress->ipv4.sin_port : socketAddress->ipv6.sin6_port);
if (addressStr && port)
{
AddressAndPort *aAndP = [[AddressAndPort alloc] init];
aAndP.address = [NSString stringWithCString:addressStr encoding:kCFStringEncodingUTF8];
aAndP.port = port;
[retVal addObject:aAndP];
}
}
}
return retVal;
}
@end
@implementation AddressAndPort
@end
[是的,我不用担心会创建很多NSObject
个实例......]