Skip to content

Instantly share code, notes, and snippets.

@EkkoG
Last active September 10, 2024 10:07
Show Gist options
  • Save EkkoG/d415efa44f2e257cd6e4d1134d25b4da to your computer and use it in GitHub Desktop.
Save EkkoG/d415efa44f2e257cd6e4d1134d25b4da to your computer and use it in GitHub Desktop.
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();
}
}
}
#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