Ошибка 10061 — сервер прослушивает, но клиент не подключается

#c #sockets #visual-c #tcp #winsock2

Вопрос:

Windows 10, Microsoft Visual Studio 2019, C

Я самостоятельно изучаю TCP-связь и использую информационную страницу WinSock2 для создания простой программы, в которой я могу отправлять данные от себя самому себе.

Я создал серверную часть программы в своем main.cpp файле, но я не уверен, где разместить код клиентской части.

Мой код является дубликатом предоставленного примера кода на веб-сайте Microsoft, так как я хочу, чтобы пример был запущен перед написанием моей собственной программы, которая будет использовать потоки. Код Сервера, Код Клиента.

Я разместил серверный и клиентский коды в отдельных программах, которые я запускаю вместе. Обе программы находятся на моем ноутбуке. Сначала я нажимаю запустить на сервере, затем через несколько секунд я нажимаю запустить на клиенте. Проблема в том, что клиент не может подключиться к серверу (получен код ошибки 10061). Я перепробовал много разных номеров портов, но ни один из них не сработал (около десяти разных номеров, в диапазоне от 1024 до 50000).

Странно то, что когда я открываю окно командной строки и набираю: netstat -abno | findstr <port_number> , оно сообщает мне, что прослушивается TCP-адрес. Он ничего не показывает ни до, ни после запуска программы, поэтому я уверен, что это связано с тем, что серверная программа запрашивает ее для прослушивания.

Вот изображение командной строки, когда я установил значение <port_number> 15280:

изображение

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

Единственное изменение в коде-это определение DEFAULT_PORT, которое я несколько раз менял, чтобы проверить разные номера портов. Я также изменил первый параметр getaddrinfo на NULL, так как у меня нет значений argc или argv. У меня было несколько инструкций printf, чтобы выяснить, где останавливается программа, но я удалил их. Кроме того, у меня нет цикла for из полного кода, я собрал фрагменты кода программы, которые я прошел от начала до конца.

Код сервера:

 
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <Windows.h>

#pragma comment (lib, "Ws2_32.lib")

#define DEFAULT_PORT "15280"
#define DEFAULT_BUFLEN 512

int main()
{
    WSADATA wsaData;
    int iResu<
    
    iResult = WSAStartup(MAKEWORD(2, 2), amp;wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %dn", iResult);
        return 1;
    }

    addrinfo *result = nullptr;
    addrinfo *ptr = nullptr;
    addrinfo hints;

    ZeroMemory(amp;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, amp;hints, amp;result);
    if (iResult != 0) {
        printf("getaddrinfo failed: %dn", iResult);
        WSACleanup();
        return 1;
    }

    SOCKET ListenSocket = INVALID_SOCKET;
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (ListenSocket == INVALID_SOCKET) {
        printf("Error at socket(): %dn", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }

    iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        printf("bind failed with error: %dn", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    freeaddrinfo(result);

    if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
        printf("Listen failed with error: %dn", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    SOCKET ClientSocket;
    ClientSocket = INVALID_SOCKET;
    ClientSocket = accept(ListenSocket, nullptr, nullptr);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed: %dn", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    char recvbuf[DEFAULT_BUFLEN];
    int iSendResu<
    int recvbuflen = DEFAULT_BUFLEN;

    do {
        iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0) {
            printf("Bytes printed: %dn", iResult);
            iSendResult = send(ClientSocket, recvbuf, iResult, 0);
            if (iSendResult == SOCKET_ERROR) {
                printf("send failed: %dn", WSAGetLastError());
                closesocket(ClientSocket);
                WSACleanup();
                return 1;
            }
            printf("Bytes sent: %dn", iSendResult);
        }
        else if (iResult == 0) {
            printf("Connection closing...n");
        }
        else {
            printf("recv failed: %dn", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }
    } while (iResult > 0);

    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed: %dn", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }
    closesocket(ClientSocket);
    WSACleanup();

    return 0;
}
 

Код клиента:

 
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

#define DEFAULT_PORT "15280"
#define DEFAULT_BUFLEN 512

int main(int argc, char **argv)
{
    WSADATA wsaData;
    int iResu<
    iResult = WSAStartup(MAKEWORD(2, 2), amp;wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %dn", iResult);
        return 1;
    }
    addrinfo* result = nullptr;
    addrinfo* ptr = nullptr;
    addrinfo hints;
    ZeroMemory(amp;hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    // first param is argv[1]
    iResult = getaddrinfo(NULL, DEFAULT_PORT, amp;hints, amp;result);
    if (iResult != 0) {
        printf("getaddrinfo failed: %dn", iResult);
        WSACleanup();
        return 1;
    }
    SOCKET ConnectSocket = INVALID_SOCKET;
    ptr = resu<
    ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
    if (ConnectSocket == INVALID_SOCKET) {
        printf("Error at socket(): %dn", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }
    iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        printf("Error: %dn", WSAGetLastError());
        closesocket(ConnectSocket);
        ConnectSocket = INVALID_SOCKET;
    }
    freeaddrinfo(result);
    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!n");
        WSACleanup();
        return 1;
    }
    int recvbuflen = DEFAULT_BUFLEN;
    const char *sendbuf = "this is a test";
    char recvbuf[DEFAULT_BUFLEN];
    
    iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR) {
        printf("send failed: %dn", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }
    printf("Bytes Sent: %dn", iResult);
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed: %dn", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    do {
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0) {
            printf("Bytes received: %dn", iResult);
        }
        else if (iResult == 0) {
            printf("Connection closedn");
        }
        else {
            printf("recv failed: %dn", WSAGetLastError());
        }
    } while (iResult > 0);

    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed: %dn", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}
 

Комментарии:

1. Сервер должен bind , затем listen и , наконец accept , accept часто находиться в цикле, чтобы вы могли продолжать принимать больше подключений. Было бы полезно, если бы вы показали свою лучшую попытку, чтобы мы могли понять, что вы пробовали, и лучше составить достойные ответы.

2. » Я не уверен, где разместить [функции accept() и bind() и listen() ] » — везде, где вы хотите, чтобы это соответствовало вашим потребностям. «Стал бы я помещать каждую из них в отдельную программу и каким-то образом запускать их одновременно? «…ты мог бы, да. Но это не является обязательным требованием. Например, вместо этого вы можете использовать connect() и bind() / listen() / accept() в отдельных потоках в рамках одной программы. » Если да, то как это делается и как я обеспечу, чтобы они работали вместе? «- просто создайте 2 отдельных проекта, скомпилируйте их и запустите. Что в этом сложного?

3. » На странице справки не показано, где следует разместить клиентскую часть кода (например, другой файл или другую отдельную программу). «- да, это так. Пример Сервера и Клиента реализован как отдельные программы. Как видно из того, что каждая из них имеет свою собственную main() функцию, и тот факт, что каждая из них задокументирована как «полное приложение», следовательно, 2 отдельные программы.

4. Я только что обновил свой вопрос, чтобы внести ясность. Моя проблема сейчас в том, что я не знаю, как запустить две программы одновременно. Я могу открыть одну программу, но другой отладчик не откроется до тех пор, пока первая программа не завершит свой запуск.

5. Вы можете запускать несколько программ одновременно, но вы не можете отлаживать две программы одновременно в 1 интегрированной среде разработки, так как отладчик может быть одновременно подключен только к 1 процессу. Поэтому либо запустите 2 отладчика, либо используйте внешнее ведение журнала для параллельной отладки программ.