Ошибка WinSock 10061

Я написал простое клиент-серверное приложение, использующее winsock. Сервер и клиент соединяются и обмениваются данными через TCP-порт 76567 (просто случайное число, которое я выбрал) на локальном хосте. Я проверил его на трех рабочих столах, на двух из которых установлена ​​XP, а на другом - Win7, я также проверил его на четырех ноутбуках, на трех с Win7 и на одном с XP. Приложение прекрасно работает на всех настольных компьютерах и на ноутбуке с XP, но на всех трех ноутбуках с Win7 я получаю ошибку 10061, когда клиент пытается подключиться к серверу!

Я отключил брандмауэр, но проблема не исчезла, я также посмотрел вокруг, чтобы выяснить причину этой ошибки, и похоже, что клиент пытается подключиться к серверу, который не слушает. Однако серверный вызов listen() успешно возвращается! Очень странно, что проблема возникает только на ноутбуках с Win7, есть идеи?

Вот мой код инициализации сокета:

// Initialise Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult != 0)
{
    printf("WSAStartup failed: %d\n", iResult);
}

// Create a server socket
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;

iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if(iResult != 0)
{
    printf("getaddrinfo failed: %d\n", iResult);
    WSACleanup();
}

// Create a socket to listen for clients
listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if(listenSocket == INVALID_SOCKET)
{
    printf("Error at socket(): %d\n", WSAGetLastError());

    freeaddrinfo(result);
    WSACleanup();
}

// Bind socket to ip address and port
iResult = bind(listenSocket, result->ai_addr, (int) result->ai_addrlen);
if(iResult == SOCKET_ERROR)
{
    printf("bind failed with error: %d\n", WSAGetLastError());

    freeaddrinfo(result);
    closesocket(listenSocket);
    WSACleanup();
}
freeaddrinfo(result);

// Listen for connection requests
if(listen(listenSocket, SOMAXCONN) != 0)
{
    printf("Listen failed with error: %d\n", WSAGetLastError());

    closesocket(listenSocket);
    WSACleanup();
}

Большое спасибо:)

2 ответа

IP-порт является 16-разрядным целым числом, поэтому максимально допустимый номер порта равен 0xFFFF (65535). То, что происходит здесь, является своего рода целочисленным переполнением. Поскольку требуемый номер порта (76567) не умещается в 16 бит, номер усекается, и используются только младшие 16 бит. Это дает вам номер порта 11031. Линия addr.sin_port = htons(76567); должен дать вам предупреждение компилятора, так как аргумент htons() не может найти uint16_t,

getaddrinfo() возвращает связанный список всех доступных адресов для данного hints критерии. Даже если у машины есть только один сетевой адаптер, ему может быть назначено несколько IP-адресов, даже для localhost. Вы привязываете сокет сервера к первой паре IP / порт, которая getaddrinfo() найдено, поэтому возможно, что клиент может пытаться подключиться к другому IP / порту, который на самом деле не прослушивает сервер, например, если сервер привязан к вашей локальной сети / интернет-IP, но клиент подключается к 127.0.0.1 вместо. Клиент не может подключиться к 127.0.0.1 если сервер не связан с 127.0.0.1,

В среде с несколькими компьютерами и несколькими IP-адресами следует использовать подстановочный знак 0.0.0.0 IP (иначе INADDR_ANY) при звонке bind(), вместо result->ai_addr, Это свяжет сокет со всеми доступными IP-адресами всех установленных сетевых адаптеров. Таким образом, клиент может подключиться к любому IP-адресу, к которому привязан сервер, включая 127.0.0.1, На самом деле, учитывая код, который вы показали, вам даже не нужно использовать getaddrinfo() совсем:

// Initialise Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult != 0)
{
    printf("WSAStartup failed: %d\n", iResult);
}

// Create an IPv4 server socket to listen for IPv4 clients
listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(listenSocket == INVALID_SOCKET)
{
    printf("Error at socket(): %d\n", WSAGetLastError());
    WSACleanup();
}

// Bind socket to IPv4 address and port
sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(76567);
addr.sin_addr.s_addr = INADDR_ANY;

iResult = bind(listenSocket, (sockaddr*)&addr, sizeof(addr));
if(iResult == SOCKET_ERROR)
{
    printf("bind failed with error: %d\n", WSAGetLastError());
    closesocket(listenSocket);
    WSACleanup();
}

// Listen for IPv4 connection requests
if(listen(listenSocket, SOMAXCONN) != 0)
{
    printf("Listen failed with error: %d\n", WSAGetLastError());
    closesocket(listenSocket);
    WSACleanup();
}
Другие вопросы по тегам