Last active
September 10, 2024 10:07
-
-
Save EkkoG/d415efa44f2e257cd6e4d1134d25b4da to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.net.Inet6Address; | |
import java.net.InetAddress; | |
import java.net.InetSocketAddress; | |
import java.net.Socket; | |
import java.net.SocketAddress; | |
public class NetworkUtils { | |
/** | |
* 获取系统为指定目的 IPv6 地址和端口选择的本地源 IPv6 地址 | |
* | |
* @param destination 目标 IPv6 地址 | |
* @param port 目标端口号 | |
* @return 系统选择的本地源 IPv6 地址 | |
* @throws Exception 如果出现错误 | |
*/ | |
public static String getSystemChosenIPv6AddressForDestination(String destination, int port) throws Exception { | |
// 解析传入的 IPv6 地址 | |
InetAddress inetAddress = Inet6Address.getByName(destination); | |
// 创建一个未绑定的 Socket | |
Socket socket = new Socket(); | |
// 创建目标地址和端口 | |
SocketAddress socketAddress = new InetSocketAddress(inetAddress, port); | |
// 连接到目标地址,底层会为这个连接选择一个本地地址 | |
socket.connect(socketAddress); | |
// 获取系统选择的本地地址 | |
InetAddress localAddress = socket.getLocalAddress(); | |
// 关闭套接字 | |
socket.close(); | |
// 将本地地址返回为字符串形式 | |
return localAddress.getHostAddress(); | |
} | |
public static void main(String[] args) { | |
try { | |
// 示例使用,目标为 Google Public DNS 的 IPv6 地址,端口为 443 | |
String destination = "2001:4860:4860::8888"; | |
int port = 443; | |
// 获取系统选择的源 IPv6 地址 | |
String chosenIPv6Address = getSystemChosenIPv6AddressForDestination(destination, port); | |
System.out.println("系统选择的源 IPv6 地址是: " + chosenIPv6Address); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
#import <netinet/in.h> | |
#import <arpa/inet.h> | |
#import <sys/socket.h> | |
#import <ifaddrs.h> | |
@interface NetworkUtils : NSObject | |
+ (NSString *)getSystemChosenIPv6AddressForDestination:(NSString *)destination port:(int)port; | |
@end | |
@implementation NetworkUtils | |
+ (NSString *)getSystemChosenIPv6AddressForDestination:(NSString *)destination port:(int)port { | |
char addrBuffer[INET6_ADDRSTRLEN]; | |
// 现在使用传入的 IPv6 地址和传入的端口号作为目标 | |
struct sockaddr_in6 dest_addr; | |
memset(&dest_addr, 0, sizeof(dest_addr)); | |
dest_addr.sin6_family = AF_INET6; | |
dest_addr.sin6_port = htons(port); // 设置传入的目标端口号 | |
// 将传入的 IPv6 地址填充到目标地址结构中 | |
if (inet_pton(AF_INET6, [destination UTF8String], &dest_addr.sin6_addr) != 1) { | |
NSLog(@"无效的目标 IPv6 地址"); | |
return nil; | |
} | |
// 创建一个套接字 | |
int sockfd = socket(AF_INET6, SOCK_DGRAM, 0); // 可以根据需要选择 SOCK_STREAM 或 SOCK_DGRAM | |
if (sockfd < 0) { | |
NSLog(@"无法创建套接字"); | |
return nil; | |
} | |
// 发起连接请求,但不会真的发送数据 | |
if (connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) { | |
NSLog(@"无法连接到目标地址"); | |
close(sockfd); | |
return nil; | |
} | |
// 获取系统选择的源地址 | |
struct sockaddr_in6 local_addr; | |
socklen_t addr_len = sizeof(local_addr); | |
if (getsockname(sockfd, (struct sockaddr *)&local_addr, &addr_len) == -1) { | |
NSLog(@"无法获取本地地址"); | |
close(sockfd); | |
return nil; | |
} | |
// 将本地地址转换为可读的字符串格式 | |
inet_ntop(AF_INET6, &local_addr.sin6_addr, addrBuffer, sizeof(addrBuffer)); | |
// 关闭套接字 | |
close(sockfd); | |
return [NSString stringWithUTF8String:addrBuffer]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment