Objective c IPv6与低级C API的兼容性问题';s
苹果需要IPv6兼容性。看起来有点过早,但我想必须有人强迫它被广泛采用 我有一个客户,他有一些旧代码,由于不兼容,将不再被批准用于应用商店。我并不是自己写这个软件的,特别是我从来没有接触过这部分代码。当涉及到低级C网络时,我不是一个很好的忍者 我告诉客户,部分问题在于他们只有一个IPv4服务器,并且让我们硬编码一个IPv4地址到该服务器。我将IPv4地址更新为域名,并告诉他们他们的服务器必须支持IPv6。所以,他们把它们移了个遍,在进行任何测试之前翻转了开关。几天前我接到通知,他们商店里的所有软件都不再工作了。这就是我们所处的困境 以下是我可能需要一些帮助的许多问题之一 不仅连接到端口的服务器不响应IPv6,而且正在使用的一些较低级别的API不兼容 我遇到的第一件事是使用Objective c IPv6与低级C API的兼容性问题';s,objective-c,c,sockets,Objective C,C,Sockets,苹果需要IPv6兼容性。看起来有点过早,但我想必须有人强迫它被广泛采用 我有一个客户,他有一些旧代码,由于不兼容,将不再被批准用于应用商店。我并不是自己写这个软件的,特别是我从来没有接触过这部分代码。当涉及到低级C网络时,我不是一个很好的忍者 我告诉客户,部分问题在于他们只有一个IPv4服务器,并且让我们硬编码一个IPv4地址到该服务器。我将IPv4地址更新为域名,并告诉他们他们的服务器必须支持IPv6。所以,他们把它们移了个遍,在进行任何测试之前翻转了开关。几天前我接到通知,他们商店里的所有软
gethostbyname()
。显然,这不支持IPv6。我一直试图用getaddrinfo()
修复它,但是我的sockaddr不太一样
我看到的第二个问题是,显然我需要使用AF_unsec
而不是AF_INET
。因此,我尝试以下列方式打开套接字:
int sockfd = socket(AF_UNSPEC, SOCK_STREAM, 0);
我总是得到-1分
如果我使用AF\u INET
打开袜子,我会走得更远,但我会遇到以下问题:
otherAddr sockaddr * 0x618000220680 0x0000618000220680
sa_len __uint8_t '\x1c'
sa_family sa_family_t '\x1e'
sa_data char [14] "\x13\x88"
otherAddrCast sockaddr * 0x7000052d3c28 0x00007000052d3c28
sa_len __uint8_t '\0'
sa_family sa_family_t '\0'
sa_data char [14] "\x13\x88\"Ԛ\\"
因此,一些sau数据
是相同的。如果我没有在中将sockaddr\u强制转换为struct sockaddr*
,那么sa\u数据
是相同的
问题是我不知道这其中的大部分意思。帮忙
编辑:这是我的代码。假设我只得到1个地址(因为我是)
您根本不应该将AF_unsec
与socket()一起使用。您必须使用AF\u INET
(IPv4)或AF\u INET6
(IPv6)
您可以将AF_unsec
与getaddrinfo()
的hints
输入参数一起使用,以指示您愿意接受IPv4和IPv6地址作为输出。输出中的实际地址将是AF\u INET
或AF\u INET6
。或者,对于仅IPv4输出,您可以将提示设置为AF\u INET
。或AF_INET6
仅用于IPv6输出
您应该循环查看getaddrinfo()
返回的列表。对于列表中的每个地址:
- 将其
ai_系列
、ai_socktype
和ai_协议
字段传递到socket()
- 然后将其
ai_addr
和ai_addrlen
字段传递到bind()
(服务器)或connect()
(客户端)
对侦听服务器报告的所有地址以及客户端报告的所有地址重复此操作,直到其中一个成功连接
这样,您创建的每个套接字都与它正在使用的地址的IP版本相匹配,并且您正在将(IPv4)中的sockaddr\u或sockaddr\u in6
(IPv6)中的sockaddr\u传递到绑定()
/连接()
成功侦听服务器套接字或成功连接客户端套接字后,如果需要使用accept()
、getsockname()
或getpeername()
从套接字检索IP,请确保向其传递一个要填充的sockaddr\u存储结构sockaddr_存储
足够大,可以容纳所有定义的基于sockaddr
的结构(而且有很多)。如果成功,则可以根据其sa_系列
字段(AF_INET
或AF_INET6
)将其强制转换为sockaddr_in 6
)。其他类似的函数也是如此,比如inet\u pton()
和inet\u ntop()
更新:根据显示的客户端代码,尝试以下操作:
struct addrinfo hints = {0};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
NSString* portString = [NSString stringWithFormat:@"%d", _port];
struct addrinfo *ai;
int sockfd = -1;
int status = getaddrinfo([_hostname UTF8String], [portString cStringUsingEncoding:kCFStringEncodingASCII] , &hints, &ai);
if (status == 0) {
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd == -1) {
status = errno;
}
else if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
status = errno;
close(sockfd);
sockfd = -1;
}
freeaddrinfo(ai);
}
if (sockfd == -1) {
// handle status error as needed...
}
else {
// use sockfd as needed...
close(sockfd);
}
struct addrinfo hints={0};
hits.ai_family=AF_INET;
hits.ai_socktype=SOCK_流;
hits.ai_protocol=IPPROTO_TCP;
NSString*端口字符串=[NSString stringWithFormat:@“%d”,port];
结构addrinfo*ai;
int sockfd=-1;
int status=getaddrinfo([\u主机名UTF8String],[portString cstringusingencode:kCFStringEncodingASCII],&hits,&ai);
如果(状态==0){
sockfd=socket(ai->ai_族,ai->ai_socktype,ai->ai_协议);
如果(sockfd==-1){
状态=错误号;
}
否则如果(连接(sockfd,ai->ai_addr,ai->ai_addrlen)<0){
状态=错误号;
关闭(sockfd);
sockfd=-1;
}
freeaddrinfo(ai);
}
如果(sockfd==-1){
//根据需要处理状态错误。。。
}
否则{
//根据需要使用sockfd。。。
关闭(sockfd);
}
您可能需要查找IPv6套接字教程。stackoverflow的问题可能有点宽泛。“似乎有点过早”-是的,只是IPv4地址刚刚用完,IPv6标准化仅20年。绝对过早…我发现非常有帮助我理解标准已经存在,不幸的是这还不够。许多消费者ISP(大多数应用程序用户)并不完全支持IPv6。如果没有合理的测试途径,这会给那些试图支持它的人带来很大的挑战。Downvoter,请解释一下为什么你会downvote。谢谢你回答我的问题。我很少处理任何低级API。我很感激你花时间去理解,尽管有这个问题,但由于在这些图书馆缺乏经验,我几乎没有办法进一步完善它。您花时间解释了我使用常量和类型的方式有什么不合理之处,而其他人只是标记了它
struct addrinfo hints = {0};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
NSString* portString = [NSString stringWithFormat:@"%d", _port];
struct addrinfo *ai;
int sockfd = -1;
int status = getaddrinfo([_hostname UTF8String], [portString cStringUsingEncoding:kCFStringEncodingASCII] , &hints, &ai);
if (status == 0) {
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd == -1) {
status = errno;
}
else if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
status = errno;
close(sockfd);
sockfd = -1;
}
freeaddrinfo(ai);
}
if (sockfd == -1) {
// handle status error as needed...
}
else {
// use sockfd as needed...
close(sockfd);
}