Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c IPv6与低级C API的兼容性问题';s_Objective C_C_Sockets - Fatal编程技术网

Objective c IPv6与低级C API的兼容性问题';s

Objective c IPv6与低级C API的兼容性问题';s,objective-c,c,sockets,Objective C,C,Sockets,苹果需要IPv6兼容性。看起来有点过早,但我想必须有人强迫它被广泛采用 我有一个客户,他有一些旧代码,由于不兼容,将不再被批准用于应用商店。我并不是自己写这个软件的,特别是我从来没有接触过这部分代码。当涉及到低级C网络时,我不是一个很好的忍者 我告诉客户,部分问题在于他们只有一个IPv4服务器,并且让我们硬编码一个IPv4地址到该服务器。我将IPv4地址更新为域名,并告诉他们他们的服务器必须支持IPv6。所以,他们把它们移了个遍,在进行任何测试之前翻转了开关。几天前我接到通知,他们商店里的所有软

苹果需要IPv6兼容性。看起来有点过早,但我想必须有人强迫它被广泛采用

我有一个客户,他有一些旧代码,由于不兼容,将不再被批准用于应用商店。我并不是自己写这个软件的,特别是我从来没有接触过这部分代码。当涉及到低级C网络时,我不是一个很好的忍者

我告诉客户,部分问题在于他们只有一个IPv4服务器,并且让我们硬编码一个IPv4地址到该服务器。我将IPv4地址更新为域名,并告诉他们他们的服务器必须支持IPv6。所以,他们把它们移了个遍,在进行任何测试之前翻转了开关。几天前我接到通知,他们商店里的所有软件都不再工作了。这就是我们所处的困境

以下是我可能需要一些帮助的许多问题之一

不仅连接到端口的服务器不响应IPv6,而且正在使用的一些较低级别的API不兼容

我遇到的第一件事是使用
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);
}