Клиент IPv6 не может подключиться к серверу IPv6 - PullRequest
0 голосов
/ 25 октября 2019

Моя программа - клиентский сервер IPv6. клиент не может установить соединение с сервером? Клиент и сервер должны использовать обратную связь, проблема в этом коде не может подключиться к серверу

   SOCKET sock = socket(AF_INET6, SOCK_STREAM, 0);
 if (sock == INVALID_SOCKET)
  {
    cerr << "Can't create socket, Err #" << WSAGetLastError() << endl;
    WSACleanup();
    return;
 }

   sockaddr_in6 hint;
hint.sin6_family = AF_INET6;
hint.sin6_port = htons(port);
hint.sin6_addr = in6addr_any;
// Connect to server
int connResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (connResult == SOCKET_ERROR)
{
    cerr << "Can't connect to server, Err #" << WSAGetLastError() 
   << endl;
    closesocket(sock);
    WSACleanup();
    return;
}

1 Ответ

0 голосов
/ 25 октября 2019

Клиентский TCP-сокет не может connect() до in6addr_any. Сервер TCP может bind() до in6addr_any, поэтому он может listen() на всех доступных локальных сетевых интерфейсах IPv6 с одним SOCKET. Но клиент должен connect() к реальному IPv6-адресу, который сервер фактически прослушивает (например, in6addr_loopback, если клиент работает на той же машине, что и сервер. Ваш сервер может использовать GetAdaptersInfo() или GetAdaptersAddresses() дляузнайте, какие локальные IP-адреса на самом деле действительны для клиента до connect() to).

Также вам необходимо полностью обнулить структуру sockaddr_in6. sockaddr_in6 имеет поля sin6_flowinfo и sin6_scope_id, которые вы не заполняете, поэтому они будут иметь случайные значения из стека. В частности, sin6_scope_id повлияет на способность connect() использовать правильный сетевой интерфейс для подключения к серверу.

SOCKET sock = socket(AF_INET6, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
    cerr << "Can't create socket, Err #" << WSAGetLastError() << endl;
    WSACleanup();
    return;
}

sockaddr_in6 hint = {};
hint.sin6_family = AF_INET6;
hint.sin6_port = htons(port);
inet_pton(AF_INET6, "server IPv6 address here", &(hint.sin6_addr));

// Connect to server
int connResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
...

Попробуйте вместо этого использовать getaddrinfo(). Пусть ОС выделит для вас правильно заполненный sockaddr_in6, который затем вы можете передать как есть на connect() (аналогично тому, как я объяснил вам в вашем предыдущем вопросе для bind()).

addrinfo hint = {};
hint.ai_family = AF_INET6;
hint.ai.socktype = SOCK_STREAM;
hint.ai_protocol = IPPROTO_TCP;

addrinfo *res;

err = getaddrinfo("server hostname or IPv6 address here", "server port here", &hint, &res);
if (err != 0)
{
    cerr << "Can't get address to connect, Err #" << WSAGetLastError() << endl;
    WSACleanup();
    return;
}

SOCKET sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock == INVALID_SOCKET)
{
    cerr << "Can't create socket, Err #" << WSAGetLastError() << endl;
    freeaddrinfo(res);
    WSACleanup();
    return;
}

// Connect to server
int connResult = connect(sock, res->ai_addr, res->ai_addrlen);
if (connResult == SOCKET_ERROR)
{
    cerr << "Can't connect to server, Err #" << WSAGetLastError() << endl;
    closesocket(sock);
    freeaddrinfo(res);
    WSACleanup();
    return;
}

freeaddrinfo(res);
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...