Objective-C:修改方法返回带IPv4/IPv6键的NSDictionary
修正方案:将服务地址转为IPv4/IPv6键值对字典
你的代码思路方向正确,但存在一个关键逻辑错误,导致所有地址都会被错误归类到IPv4键下:NSString *key = AF_INET ? @"IPv4" : @"IPv6"; 这行直接用AF_INET作为判断条件,而AF_INET是一个非零常量(值为2),条件永远为真,因此永远返回@"IPv4"。
下面是修正后的完整代码:
+ (NSDictionary<NSString *, NSString *> *)addressesFromService:(NSNetService *)service { NSMutableDictionary<NSString *, NSString *> *result = [NSMutableDictionary dictionary]; char addressBuffer[INET6_ADDRSTRLEN]; for (NSData *data in service.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) ); if (addressStr) { // 修正:根据当前地址的协议族选择对应键 NSString *key = (socketAddress->sa.sa_family == AF_INET) ? @"IPv4" : @"IPv6"; result[key] = [NSString stringWithUTF8String:addressStr]; } } } return [result copy]; }
额外说明
如果一个服务可能存在多个同类型IP地址(比如多个IPv4或IPv6),上面的代码会用最后一个地址覆盖之前的。如果需要保留所有同类型地址,可以把字典的值类型改为数组,修改后的代码如下:
+ (NSDictionary<NSString *, NSArray<NSString *> *> *)addressesFromService:(NSNetService *)service { NSMutableDictionary<NSString *, NSMutableArray<NSString *> *> *result = [NSMutableDictionary dictionary]; char addressBuffer[INET6_ADDRSTRLEN]; for (NSData *data in service.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) ); if (addressStr) { NSString *key = (socketAddress->sa.sa_family == AF_INET) ? @"IPv4" : @"IPv6"; // 初始化数组(如果不存在) if (!result[key]) { result[key] = [NSMutableArray array]; } [result[key] addObject:[NSString stringWithUTF8String:addressStr]]; } } } return [result copy]; }
内容的提问来源于stack exchange,提问作者Jerry Seigle
相关产品推荐
相关产品推荐

