C 中 IPv6 连接的问题
Problems with IPv6 connect in C
我正在尝试编写一个可以接受 IPv4 和 IPv6 连接的不可知回显服务器。我正在使用 addrinfo 结构,使用 getaddrinfo 进行设置。
Ipv4 连接没有问题,但我无法获得有效的 ipV6 连接。
我认为我的问题可能是由于错误的 getaddrinfo 参数造成的,但我看不出哪里出错了。
这是我的代码
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int simpleSocket = 0, simplePort = 0,returnStatus = 0, n;
char buffer[1024] = "";
struct hostent *hostinfo;
struct addrinfo simpleServer, *res;
if (3 != argc) {
fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]);
exit(1);
}
simplePort = atoi(argv[2]);
memset(&simpleServer, 0, sizeof simpleServer);
simpleServer.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
simpleServer.ai_socktype = SOCK_STREAM;
simpleServer.ai_flags = AI_PASSIVE; // fill in my IP for me
returnStatus = getaddrinfo(argv[1], argv[2], &simpleServer, &res);
simpleSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
char *s = NULL;
switch(res->ai_addr->sa_family) {
case AF_INET: {
struct sockaddr_in *addr_in = (struct sockaddr_in *)res;
s = malloc(INET_ADDRSTRLEN);
inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
break;
}
case AF_INET6: {
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res;
s = malloc(INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
break;
}
default:
break;
}
fprintf(stdout, "IP address: %s\n", s);
returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
fprintf(stdout, "Type a message \n");
memset(buffer, '[=10=]', strlen(buffer));
fgets(buffer, sizeof(buffer), stdin);
returnStatus = write(simpleSocket, buffer, sizeof(buffer));
memset(&buffer, '[=10=]', sizeof(buffer));
fprintf(stdout, "Waiting server..\n");
returnStatus = read(simpleSocket, buffer, sizeof(buffer));
fprintf(stdout, "Message: %s\n", buffer);
close(simpleSocket);
return 0;
}
server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int simpleSocket = 0, simplePort = 0, returnStatus = 0, check = 1, n;
char buffer[1024];
struct addrinfo simpleServer, *res;
if (2 != argc) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
simplePort = atoi(argv[1]);
memset(&simpleServer, 0, sizeof simpleServer);
simpleServer.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
simpleServer.ai_socktype = SOCK_STREAM;
simpleServer.ai_flags = AI_PASSIVE; // fill in my IP for me
getaddrinfo(NULL, argv[1], &simpleServer, &res);
simpleSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
returnStatus =bind(simpleSocket, res->ai_addr, res->ai_addrlen);
returnStatus = listen(simpleSocket, 5);
struct addrinfo clientName = { 0 };
int clientNameLength = sizeof(clientName);
int simpleChildSocket = 0;
while (1) {
while (1) {
simpleChildSocket = accept(simpleSocket,(struct sockaddr *)&clientName, &clientNameLength);
fprintf(stdout,"Waiting..\n");
memset(&buffer, '[=11=]', sizeof(buffer));
returnStatus = read(simpleChildSocket, buffer, sizeof(buffer));
fprintf(stdout, "Message: %s\n", buffer);
write(simpleChildSocket, buffer, sizeof(buffer));
}
}
close(simpleChildSocket);
close(simpleSocket);
return 0;
}
正如@JoachimPileborg 在评论中提到的,问题是您的服务器代码没有为 getaddrinfo()
给您的每个地址打开监听套接字。您在 simpleServer
结构中指定 AF_UNSPEC
,因此 getaddrinfo()
将为您提供 IPv4 和 IPv6 地址的列表。您正在为该列表中的第一个条目创建一个监听套接字,它恰好是一个 IPv4 地址。这就是您的 IPv4 客户端成功而 IPv6 客户端失败的原因。您需要遍历列表,为每个条目创建一个单独的监听套接字。
您还犯了其他错误,比如每次调用 accept()
时都没有重置 clientNameLength
变量,在您应该使用 addrinfo
作为 clientName
缓冲区时使用 sockaddr_storage
而不是注意 read()
.
的 return 值
试试像这样的东西:
include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <poll.h>
#define MAX_SERVERS 10
#define MAX_CLIENTS 50
#define MAX_SOCKETS (MAX_SERVERS + MAX_CLIENTS)
int main(int argc, char *argv[])
{
int simpleSocket, simplePort, returnStatus, n, m;
char buffer[1024];
pollfd simpleSockets[MAX_SOCKETS];
int numSockets = 0, numServers = 0;
struct addrinfo simpleServer, *res, *addr;
if (2 != argc)
{
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
simplePort = atoi(argv[1]);
memset(&simpleServer, 0, sizeof simpleServer);
simpleServer.ai_family = AF_UNSPEC; // use IPv4 and/or IPv6, whatever is available
simpleServer.ai_socktype = SOCK_STREAM;
simpleServer.ai_flags = AI_PASSIVE; // fill in my IP for me
if (0 != getaddrinfo(NULL, argv[1], &simpleServer, &res))
{
fprintf(stderr, "getaddrinfo failed\n");
exit(1);
}
addr = res;
while (NULL != addr)
{
simpleSocket = socket(res->ai_family, addr->ai_socktype, addr->ai_protocol);
if (-1 == simpleSocket)
{
fprintf(stderr, "socket failed\n");
}
else
{
returnStatus = bind(simpleSocket, addr->ai_addr, addr->ai_addrlen);
if (0 == returnStatus)
returnStatus = listen(simpleSocket, 5);
if (0 == returnStatus)
{
simpleSockets[numSockets].fd = simpleSocket;
simpleSockets[numSockets].events = POLLIN;
simpleSockets[numSockets].revents = 0;
++numSockets;
++numServers;
if (MAX_SERVERS == numServers)
break;
}
else
{
fprintf(stderr, "bind/listen failed\n");
close(simpleSocket);
}
}
addr = addr->next;
}
freeaddrinfo(res);
if (0 == numServers)
{
fprintf(stderr, "no servers are listening\n");
exit(1);
}
struct sockaddr_storage clientName;
int clientNameLength;
while (1)
{
returnStatus = poll(simpleSockets, numSockets, -1);
if (-1 == returnStatus)
{
fprintf(stderr, "poll failed\n");
exit(1);
}
if (0 == returnStatus)
continue;
for (n = 0; n < numSockets; ++n)
{
if (simpleSockets[n].revents & POLLIN)
{
if (n < numServers)
{
clientNameLength = sizeof(clientName);
simpleSocket = accept(simpleSockets[n].fd, (struct sockaddr *)&clientName, &clientNameLength);
if (-1 == simpleSocket)
{
fprintf(stderr, "accept failed\n");
continue;
}
for (m = numServers; m < numSockets; ++m)
{
if (-1 == simpleSockets[m].fd)
{
simpleSockets[m].fd = simpleSocket;
simpleSockets[m].events = POLLIN;
simpleSockets[m].revents = 0;
simpleSocket = -1;
break;
}
}
if ((-1 != simpleSocket) && (MAX_SOCKETS > numSockets))
{
simpleSockets[numSockets].fd = simpleSocket;
simpleSockets[numSockets].events = POLLIN;
simpleSockets[numSockets].revents = 0;
++numSockets;
simpleSocket = -1;
}
if (-1 != simpleSocket)
{
fprintf(stderr, "Too many clients connected\n");
close(simpleSocket);
}
else
fprintf(stdout, "Client connected\n");
}
else
{
returnStatus = read(simpleSockets[n].fd, buffer, sizeof(buffer));
if (0 >= returnStatus)
{
if (0 > returnStatus)
fprintf(stdout, "Client error, disconnecting\n");
else
fprintf(stdout, "Client disconnected\n");
close(simpleSockets[n].fd);
simpleSockets[n].fd = -1;
simpleSockets[n].events = 0;
simpleSockets[n].revents = 0;
continue;
}
fprintf(stdout, "Message: %.*s\n", returnStatus, buffer);
write(simpleSockets[n].fd, buffer, returnStatus);
}
}
if (simpleSockets[n].revents & (POLLERR|POLLHUP|POLLNVAL))
{
if (simpleSockets[n].revents & POLLHUP)
fprintf(stdout, "Client disconnected\n");
else if (n >= numServers)
fprintf(stdout, "Client error, disconnecting\n");
else
fprintf(stdout, "Server error, closing\n");
close(simpleSockets[n].fd);
simpleSockets[n].fd = -1;
simpleSockets[n].events = 0;
simpleSockets[n].revents = 0;
}
}
}
for (n = 0; n < numSockets; ++n)
{
if (-1 != simpleSockets[n].fd)
close(simpleSockets[n].fd);
}
return 0;
}
也就是说,如果您 运行 在支持 dual-stack 套接字的平台上,您的服务器不必创建任何 IPv4 侦听套接字根本。它只能创建 IPv6 套接字,然后禁用它们的 IPV6_V6ONLY
选项。这将允许他们接受 IPv4 和 IPv6 客户端。由 accept()
编辑的客户端地址 return 将告诉您是否已连接 IPv4 或 IPv6 客户端。
memset(&simpleServer, 0, sizeof simpleServer);
simpleServer.ai_family = AF_INET6;
simpleServer.ai_socktype = SOCK_STREAM;
simpleServer.ai_flags = AI_PASSIVE;
if (0 != getaddrinfo(NULL, argv[1], &simpleServer, &res))
{
fprintf(stderr, "getaddrinfo failed\n");
exit(1);
}
addr = res;
while (NULL != addr)
{
simpleSocket = socket(res->ai_family, addr->ai_socktype, addr->ai_protocol);
if (-1 == simpleSocket)
{
fprintf(stderr, "socket failed\n");
}
else
{
n = 0;
returnStatus = setsockopt(simpleSocket, IPPROTO_IPV6, IPV6_V6ONLY, &n, sizeof(n));
...
}
addr = addr->next;
}
...
client.c 代码有缺陷,它将完整的地址信息存储在 sockaddr_in 结构中。
res 的类型为 addrinfo
(http://man7.org/linux/man-pages/man3/getaddrinfo.3.html)
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
所以而不是
struct sockaddr_in *addr_in = (struct sockaddr_in *)res;
它应该是
struct sockaddr_in *addr_in = (struct sockaddr_in *)res->ai_addr;
喜欢
case AF_INET: {
struct sockaddr_in *addr_in = (struct sockaddr_in *)res->ai_addr;
s = malloc(INET_ADDRSTRLEN);
inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
break;
}
case AF_INET6: {
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res->ai_addr;
s = malloc(INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
break;
}
此修改后代码按预期工作。
我正在尝试编写一个可以接受 IPv4 和 IPv6 连接的不可知回显服务器。我正在使用 addrinfo 结构,使用 getaddrinfo 进行设置。
Ipv4 连接没有问题,但我无法获得有效的 ipV6 连接。
我认为我的问题可能是由于错误的 getaddrinfo 参数造成的,但我看不出哪里出错了。
这是我的代码
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int simpleSocket = 0, simplePort = 0,returnStatus = 0, n;
char buffer[1024] = "";
struct hostent *hostinfo;
struct addrinfo simpleServer, *res;
if (3 != argc) {
fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]);
exit(1);
}
simplePort = atoi(argv[2]);
memset(&simpleServer, 0, sizeof simpleServer);
simpleServer.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
simpleServer.ai_socktype = SOCK_STREAM;
simpleServer.ai_flags = AI_PASSIVE; // fill in my IP for me
returnStatus = getaddrinfo(argv[1], argv[2], &simpleServer, &res);
simpleSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
char *s = NULL;
switch(res->ai_addr->sa_family) {
case AF_INET: {
struct sockaddr_in *addr_in = (struct sockaddr_in *)res;
s = malloc(INET_ADDRSTRLEN);
inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
break;
}
case AF_INET6: {
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res;
s = malloc(INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
break;
}
default:
break;
}
fprintf(stdout, "IP address: %s\n", s);
returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
fprintf(stdout, "Type a message \n");
memset(buffer, '[=10=]', strlen(buffer));
fgets(buffer, sizeof(buffer), stdin);
returnStatus = write(simpleSocket, buffer, sizeof(buffer));
memset(&buffer, '[=10=]', sizeof(buffer));
fprintf(stdout, "Waiting server..\n");
returnStatus = read(simpleSocket, buffer, sizeof(buffer));
fprintf(stdout, "Message: %s\n", buffer);
close(simpleSocket);
return 0;
}
server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int simpleSocket = 0, simplePort = 0, returnStatus = 0, check = 1, n;
char buffer[1024];
struct addrinfo simpleServer, *res;
if (2 != argc) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
simplePort = atoi(argv[1]);
memset(&simpleServer, 0, sizeof simpleServer);
simpleServer.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
simpleServer.ai_socktype = SOCK_STREAM;
simpleServer.ai_flags = AI_PASSIVE; // fill in my IP for me
getaddrinfo(NULL, argv[1], &simpleServer, &res);
simpleSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
returnStatus =bind(simpleSocket, res->ai_addr, res->ai_addrlen);
returnStatus = listen(simpleSocket, 5);
struct addrinfo clientName = { 0 };
int clientNameLength = sizeof(clientName);
int simpleChildSocket = 0;
while (1) {
while (1) {
simpleChildSocket = accept(simpleSocket,(struct sockaddr *)&clientName, &clientNameLength);
fprintf(stdout,"Waiting..\n");
memset(&buffer, '[=11=]', sizeof(buffer));
returnStatus = read(simpleChildSocket, buffer, sizeof(buffer));
fprintf(stdout, "Message: %s\n", buffer);
write(simpleChildSocket, buffer, sizeof(buffer));
}
}
close(simpleChildSocket);
close(simpleSocket);
return 0;
}
正如@JoachimPileborg 在评论中提到的,问题是您的服务器代码没有为 getaddrinfo()
给您的每个地址打开监听套接字。您在 simpleServer
结构中指定 AF_UNSPEC
,因此 getaddrinfo()
将为您提供 IPv4 和 IPv6 地址的列表。您正在为该列表中的第一个条目创建一个监听套接字,它恰好是一个 IPv4 地址。这就是您的 IPv4 客户端成功而 IPv6 客户端失败的原因。您需要遍历列表,为每个条目创建一个单独的监听套接字。
您还犯了其他错误,比如每次调用 accept()
时都没有重置 clientNameLength
变量,在您应该使用 addrinfo
作为 clientName
缓冲区时使用 sockaddr_storage
而不是注意 read()
.
试试像这样的东西:
include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <poll.h>
#define MAX_SERVERS 10
#define MAX_CLIENTS 50
#define MAX_SOCKETS (MAX_SERVERS + MAX_CLIENTS)
int main(int argc, char *argv[])
{
int simpleSocket, simplePort, returnStatus, n, m;
char buffer[1024];
pollfd simpleSockets[MAX_SOCKETS];
int numSockets = 0, numServers = 0;
struct addrinfo simpleServer, *res, *addr;
if (2 != argc)
{
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
simplePort = atoi(argv[1]);
memset(&simpleServer, 0, sizeof simpleServer);
simpleServer.ai_family = AF_UNSPEC; // use IPv4 and/or IPv6, whatever is available
simpleServer.ai_socktype = SOCK_STREAM;
simpleServer.ai_flags = AI_PASSIVE; // fill in my IP for me
if (0 != getaddrinfo(NULL, argv[1], &simpleServer, &res))
{
fprintf(stderr, "getaddrinfo failed\n");
exit(1);
}
addr = res;
while (NULL != addr)
{
simpleSocket = socket(res->ai_family, addr->ai_socktype, addr->ai_protocol);
if (-1 == simpleSocket)
{
fprintf(stderr, "socket failed\n");
}
else
{
returnStatus = bind(simpleSocket, addr->ai_addr, addr->ai_addrlen);
if (0 == returnStatus)
returnStatus = listen(simpleSocket, 5);
if (0 == returnStatus)
{
simpleSockets[numSockets].fd = simpleSocket;
simpleSockets[numSockets].events = POLLIN;
simpleSockets[numSockets].revents = 0;
++numSockets;
++numServers;
if (MAX_SERVERS == numServers)
break;
}
else
{
fprintf(stderr, "bind/listen failed\n");
close(simpleSocket);
}
}
addr = addr->next;
}
freeaddrinfo(res);
if (0 == numServers)
{
fprintf(stderr, "no servers are listening\n");
exit(1);
}
struct sockaddr_storage clientName;
int clientNameLength;
while (1)
{
returnStatus = poll(simpleSockets, numSockets, -1);
if (-1 == returnStatus)
{
fprintf(stderr, "poll failed\n");
exit(1);
}
if (0 == returnStatus)
continue;
for (n = 0; n < numSockets; ++n)
{
if (simpleSockets[n].revents & POLLIN)
{
if (n < numServers)
{
clientNameLength = sizeof(clientName);
simpleSocket = accept(simpleSockets[n].fd, (struct sockaddr *)&clientName, &clientNameLength);
if (-1 == simpleSocket)
{
fprintf(stderr, "accept failed\n");
continue;
}
for (m = numServers; m < numSockets; ++m)
{
if (-1 == simpleSockets[m].fd)
{
simpleSockets[m].fd = simpleSocket;
simpleSockets[m].events = POLLIN;
simpleSockets[m].revents = 0;
simpleSocket = -1;
break;
}
}
if ((-1 != simpleSocket) && (MAX_SOCKETS > numSockets))
{
simpleSockets[numSockets].fd = simpleSocket;
simpleSockets[numSockets].events = POLLIN;
simpleSockets[numSockets].revents = 0;
++numSockets;
simpleSocket = -1;
}
if (-1 != simpleSocket)
{
fprintf(stderr, "Too many clients connected\n");
close(simpleSocket);
}
else
fprintf(stdout, "Client connected\n");
}
else
{
returnStatus = read(simpleSockets[n].fd, buffer, sizeof(buffer));
if (0 >= returnStatus)
{
if (0 > returnStatus)
fprintf(stdout, "Client error, disconnecting\n");
else
fprintf(stdout, "Client disconnected\n");
close(simpleSockets[n].fd);
simpleSockets[n].fd = -1;
simpleSockets[n].events = 0;
simpleSockets[n].revents = 0;
continue;
}
fprintf(stdout, "Message: %.*s\n", returnStatus, buffer);
write(simpleSockets[n].fd, buffer, returnStatus);
}
}
if (simpleSockets[n].revents & (POLLERR|POLLHUP|POLLNVAL))
{
if (simpleSockets[n].revents & POLLHUP)
fprintf(stdout, "Client disconnected\n");
else if (n >= numServers)
fprintf(stdout, "Client error, disconnecting\n");
else
fprintf(stdout, "Server error, closing\n");
close(simpleSockets[n].fd);
simpleSockets[n].fd = -1;
simpleSockets[n].events = 0;
simpleSockets[n].revents = 0;
}
}
}
for (n = 0; n < numSockets; ++n)
{
if (-1 != simpleSockets[n].fd)
close(simpleSockets[n].fd);
}
return 0;
}
也就是说,如果您 运行 在支持 dual-stack 套接字的平台上,您的服务器不必创建任何 IPv4 侦听套接字根本。它只能创建 IPv6 套接字,然后禁用它们的 IPV6_V6ONLY
选项。这将允许他们接受 IPv4 和 IPv6 客户端。由 accept()
编辑的客户端地址 return 将告诉您是否已连接 IPv4 或 IPv6 客户端。
memset(&simpleServer, 0, sizeof simpleServer);
simpleServer.ai_family = AF_INET6;
simpleServer.ai_socktype = SOCK_STREAM;
simpleServer.ai_flags = AI_PASSIVE;
if (0 != getaddrinfo(NULL, argv[1], &simpleServer, &res))
{
fprintf(stderr, "getaddrinfo failed\n");
exit(1);
}
addr = res;
while (NULL != addr)
{
simpleSocket = socket(res->ai_family, addr->ai_socktype, addr->ai_protocol);
if (-1 == simpleSocket)
{
fprintf(stderr, "socket failed\n");
}
else
{
n = 0;
returnStatus = setsockopt(simpleSocket, IPPROTO_IPV6, IPV6_V6ONLY, &n, sizeof(n));
...
}
addr = addr->next;
}
...
client.c 代码有缺陷,它将完整的地址信息存储在 sockaddr_in 结构中。
res 的类型为 addrinfo
(http://man7.org/linux/man-pages/man3/getaddrinfo.3.html)
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
所以而不是
struct sockaddr_in *addr_in = (struct sockaddr_in *)res;
它应该是
struct sockaddr_in *addr_in = (struct sockaddr_in *)res->ai_addr;
喜欢
case AF_INET: {
struct sockaddr_in *addr_in = (struct sockaddr_in *)res->ai_addr;
s = malloc(INET_ADDRSTRLEN);
inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
break;
}
case AF_INET6: {
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res->ai_addr;
s = malloc(INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
returnStatus = connect(simpleSocket, res->ai_addr, res->ai_addrlen);
break;
}
此修改后代码按预期工作。