Я пытался написать простую программу чата на C ++ и столкнулся с проблемой сокетов. Следующий код возвращается
Последний код ошибки был (1): 0
Последний код ошибки был (2): 0
Последний код ошибки был (3): 10049
Последний код ошибки был (4): 10022
После проверки страницы MSDN на наличие ошибок WSA я обнаружил, что 10022 был для недопустимого аргумента, а 10049 пытался привязаться к недоступному адресу. Я пришел к выводу, что ошибка 10049 вызывала ошибку 10022, когда я пытался прослушивать несвязанный сокет.
После этого попробовал несколько разных адресов, чтобы найти ЛЮБОЙ доступный адрес, включая 127.x.x.x, 192.168.x.x, 0.0.0.0, ни один из которых не работал. Я прыгнул в CMD и увидел, что эти процессы используют другие процессы. Может ли кто-нибудь указать мне правильное направление, чтобы найти корень этой проблемы?
Решение
Во-первых, общее примечание: вам нужно проверять возвращаемое значение каждой вызываемой функции и распечатывать значение WSAGetLastError () только в том случае, если возвращаемое значение указывает на то, что функция вернула ошибку. В противном случае вы можете запутаться, только взглянув на значения кода ошибки, оставшиеся от предыдущих вызовов, и не будете иметь ничего общего с последним вызовом. То есть вместо этого:
bind(sock_CONNECTION, (SOCKADDR *)&ADDRESS, AddressSize);
printf(“Last error code was(3): %d
“, WSAGetLastError());
Тем не менее, я думаю, что конкретная проблема здесь:
ADDRESS.sin_addr.s_addr = inet_pton(AF_INET, (const CHAR*)&addr, &buffer);
inet_pton() не возвращает адрес; скорее он возвращает «1, если адрес был действительным для указанного семейства адресов, или 0, если адрес не был разбираем в указанном семействе адресов, или -1, если произошла какая-то системная ошибка (в этом случае будет установлено значение errno)». Таким образом, значение, которое вы записываете в ADDRESS.sin_addr.s_addr, равно -1, 0 или 1; ни один из них не является допустимым адресом, который bind () захочет использовать. (Ну, на самом деле 0 может быть использовано; см. Ниже, но вызов все еще не так)
Правильный способ вызова inet_pton () будет выглядеть примерно так:
int result = inet_pton(AF_INET, addr, &ADDRESS.sin_addr);
if (result != 1) printf(“inet_pton() failed, error code %d
“, WSAGetLastError());
// INADDR_ANY (aka 0) means “I don’t care which network interface, accept connections on any of them”ADDRESS.sin_addr.s_addr = INADDR_ANY;
Код с серверной реализацией взят из http://www.planetchili.net/forum/viewtopic.php?f=3&т = 3433
bind() Функция используется для указания того, какой адрес серверной системы используется для приема соединений от удаленных клиентов, а не для указания, какому удаленному клиенту разрешено подключаться к серверу. bind() Функция может использоваться только с адресами, которые действительны для самого сервера, но не для адресов удаленных устройств или хостов.
Чтобы определить, какому удаленному хосту разрешено подключаться к вашему серверу, вам необходимо принять подключение и подтвердить удаленный адрес в это время. Если адрес не правильный, соединение закрывается.
В общем, вы хотите использовать INADDR_ANY если ваш сервер не является многодомным (более одного физического подключения к нескольким сетям), и только тогда, если вы пытаетесь ограничить подключения к одной из сетей, к которым подключен ваш сервер.
Другие решения
вы получите список адресов ip4 / ip6, затем вы можете выбрать один из них и привязать свой сервер, однако этот метод действительно скучный, поэтому альтернативой является привязка к INADDR_ANY так что вы позволяете системе делать работу за вас.
вам нужно только с клиента ввести адрес сервера и порт и подключиться.