Winsock не может подключиться к локальному хосту

Для моего проекта я не могу отладить программу, поэтому я не могу быть уверен, почему возникает эта ошибка.

Мой сервер, размещенный на С#, не может подключиться к серверу на локальном хосте.

Вместо того, чтобы отправить обратно сигнал «подключение» к моему серверу, он никогда не подключается, я думаю, что код написан хорошо, и я не вижу никаких ошибок, возможно, я где-то допустил ошибку по невнимательности.

Кроме того, я ДОЛЖЕН использовать gethostbyname вместо getaddrinfo

пространство имен winsock:

SOCKET WinSock::ConnectToServer(PCHAR IP, USHORT Port)
{
    WSADATA WSA;
    if (WSAStartup(MAKEWORD(2, 0), &WSA))
    {
        SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s != SOCKET_ERROR)
        {
            hostent *Host = gethostbyname(IP);
            if (Host != ERROR)
            {
                SOCKADDR_IN Addr;

                Addr.sin_family = AF_INET;
                Addr.sin_port = htons(Port);
                Addr.sin_addr.s_addr = NULL;

                if (bind(s, PSOCKADDR(&Addr), sizeof(Addr)) > 0)
                {
                    return s;
                }
            }
        }
    }

    return FALSE;
}

BOOL WinSock::SendData(SOCKET s, PBYTE Packet)
{
    DWORD PacketSize = lstrlenA(PCHAR(Packet));
    if (send(s, PCHAR(&PacketSize), 8, 0) > NULL)
    {
        if (send(s, PCHAR(Packet), PacketSize, 0) > NULL)
        {
            return TRUE;
        }
    }
    return FALSE;
}

основной метод:

int main()
{
    char key = 1;
    SOCKET S = WinSock::ConnectToServer(0, 55480);
    while(true)
    {
        WinSock:SendData(S, (PBYTE)key);
    }
}

Вы не видите никаких ошибок, потому что нет абсолютно никакой проверки кода на наличие ошибок и сообщения об этом. Но send возвращает ssize_t, так что не стоит сравнивать это с NULL. И bind возвращает либо 0, либо отрицательное число, но не положительное целое. Так что сравнивать > 0 бесполезно.

Cheatah 14.12.2020 13:25

@Cheatah, я отключил crt, поэтому я даже не могу проверить ошибки, я должен их знать.

pillpopper228 14.12.2020 13:32

@Cheatah, так с чем мне сравнить привязку? == 0/ОШИБКА_УСПЕХА?

pillpopper228 14.12.2020 13:34

опубликованный код использует несколько конструкций кода C++ (которые не могут быть скомпилированы в C). Пожалуйста, удалите тег c

user3629249 14.12.2020 23:53

функция: send() возвращает ssize_t, а не указатель, например NULL`

user3629249 14.12.2020 23:57

касательно; * не удается подключиться к серверу на локальном хосте * SOCKET S = WinSock::ConnectToServer(0, 55480); IP-адрес локального хоста: «127.0.0.1», а не 0 и не NULL. Функция возвращает <0, если она терпит неудачу

user3629249 15.12.2020 00:03

относительно: hostent *Host = gethostbyname(IP); 1) возвращаемый указатель предназначен для struct hostent, а не для hostent. 2) передаваемый «IP» (фактически) NULL, а не указатель на 127.0.0.1 3) функция: gethostbyname() устарела. Предлагаю: getaddrinfo(). 4) предлагаем вам узнать о: getlasterror()

user3629249 15.12.2020 00:17

относительно вызова bind() со страницы MAN: в случае успеха возвращается ноль. При ошибке возвращается -1, и errno устанавливается соответствующим образом.

user3629249 15.12.2020 00:20

ПРИМЕЧАНИЕ: функции ветроуказателя уже написаны. Вы не заменяете функции, вам просто нужно сделать соответствующие вызовы в эту библиотеку с соответствующими параметрами.

user3629249 15.12.2020 00:24

одно важное соображение: разрешает ли ваш брандмауэр связь через порт: 55480?

user3629249 15.12.2020 00:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
10
511
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

            if (bind(s, PSOCKADDR(&Addr), sizeof(Addr)) > 0)

Описание этого кода заключается в том, что он должен подключаться к серверу. Но проблема в том, что bind() не подключается ни к одному серверу. Он только связывает сокет с локальным портом. Это то, что делают серверы, которые прослушивают сокеты. Предположительно, это тот же порт, который сервер уже открыл, поэтому bind() не работает. Если сервер не слушал bind(), по иронии судьбы, все получится. Но он все равно ни к чему не будет подключен.

Вы хотите использовать connect(), а не bind().

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

Ответ принят как подходящий

На самом деле вы не подключаетесь к серверу. Вы вызываете bind() для привязки клиентского сокета к локальному порту 55480, но это не создает соединения. Вместо этого вам нужно вызвать connect(), чтобы подключить клиентский сокет к удаленному порту 55480.

Кроме того, ваш SendData() закодирован неправильно. Он говорит send() отправить 8 байтов для PacketSize, но DWORD имеет размер всего 4 байта. И send() не возвращает NULL при неудаче. И send() не гарантирует отправку всех запрошенных байтов, поэтому вам нужно вызвать его в цикле. И принято отправлять многобайтовые целые числа в сетевом порядке байтов (big endian).

Кроме того, вы закодировали SendData() для ожидания строки в стиле C с нулевым завершением, но это не то, что ваш main() на самом деле передает ей.

Попробуйте еще что-нибудь вроде этого:

bool WinSock::Init()
{
    WSADATA WSA;
    return (WSAStartup(MAKEWORD(2, 0), &WSA) == 0);
}

bool WinSock::Cleanup()
{
    return (WSACleanup() == 0);
}

SOCKET WinSock::ConnectToServer(const char *IP, unsigned short Port)
{
    hostent *Host = gethostbyname(IP);
    if ((Host != NULL) && (Host->h_addrtype == AF_INET)
    {
        SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s != INVALID_SOCKET)
        {
            SOCKADDR_IN Addr = {};

            Addr.sin_family = AF_INET;
            Addr.sin_port = htons(Port);
            Addr.sin_addr.s_addr = * (u_long*) Host->h_addr;

            if (connect(s, PSOCKADDR(&Addr), sizeof(Addr)) != SOCKET_ERROR)
            {
                return s;
            }

            closesocket(s);
        }
    }

    return INVALID_SOCKET;
}

bool WinSock::Close(SOCKET s)
{
    return (closesocket(s) == 0);
}

bool WinSock::SendData(SOCKET s, const void* Data, DWORD DataSize)
{
    const char *ptr = (const char*) Data;

    while (DataSize > 0)
    {
        int numSent = send(s, ptr, DataSize, 0);
        if (numSent == SOCKET_ERROR) return false;
        ptr += numSent;
        DataSize -= numSent;
    }

    return true;
}

bool WinSock::SendData(SOCKET s, const char *Packet)
{
    DWORD PacketSize = lstrlenA(Packet);
    DWORD tmp = htonl(PacketSize);
    if (!SendData(s, &tmp, sizeof(tmp)) return false;
    return SendData(s, Packet, PacketSize);
}
int main()
{
    if (WinSock::Init())
    {
        const char *key = "1";
        SOCKET S = WinSock::ConnectToServer(NULL, 55480);
        if (s != INVALID_SOCKET)
        {
            while (true)
            {
                WinSock:SendData(S, key);
            }
            WinSock::Close(s);
        }
        WinSock::Cleanup();
    }

    return 0;
}

Другие вопросы по теме