Как отключить клиента, но сохранить сокет, WINAPI, сокеты в C

Я делаю программу чата сервер/клиент на C, используя winapi для сокетов. В том, что у меня есть часть кода, которая проверяет определенный ввод от клиента, например пароль, и, если ввод неправильный, я хочу отключить клиента и подготовиться к принятию другого подключения. Меня беспокоит то, что я должен использовать shutdown() или close()? И откуда я должен отскочить назад, чтобы дождаться другого соединения? Это пример кода:

// Preparing socket with WSAStartup(), getaddrinfo(), socket(), bind() and freeaddrinfo()

conec_again:

    if (listen(sockServ, SOMAXCONN) == SOCKET_ERROR)
    {
        std::cout << "listen() failed: " << WSAGetLastError() << '\n';
        closesocket(sockServ);
        WSACleanup();
        return 5;
    }

    if ((sock = accept(sockServ, 0, 0)) == INVALID_SOCKET)
    {
        std::cout << "accept() failed: " << WSAGetLastError() << '\n';
        closesocket(sockServ);
        WSACleanup();
        return 6;
    }

    recv(sock, Resposta, BUFTAM, 0);
    if (CompMat(Resposta, test_mat, BUFTAM)) // My implementation to compare matrices
    {
        std::cout << "Trying again.\n";  // Placeholder text
        goto conec_again;
    }

// Stuff...

Да, это делается на C++, как вы видите, используется std::cout, но это временно, и я буду делать большинство вещей на C.

Как мне отключить клиента и правильно ли эта goto часть ждать другого клиента?

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

Jerry Jeremiah 21.07.2023 05:23

Ваш заголовок не соответствует вашему вопросу. Что касается вашего заголовка, это невозможно: отключенный сокет TCP нельзя использовать повторно. Что касается вашего вопроса, вы должны использовать close(). Вы также можете вызвать shutdown(), если знаете, почему вы это делаете, но вы должны использовать close() в любом случае. Вы не сохраняете результат recv() и не проверяете его на наличие ошибок. Вы не можете серьезно предлагать написать goto в наши дни, спустя 60 лет после того, как они были признаны вредными. Используйте петлю while и continue. Не пишите такой код. Вам нужно хорошенько взглянуть на достойный учебник по сети.

user207421 21.07.2023 05:36

@user207421 user207421 «отключенный TCP-сокет нельзя использовать повторно» - на самом деле, в Windows это возможно, но только если вы используете DisconnectEx() с флагом TF_REUSE_SOCKET, а затем AcceptEx() (или ConnectEx()), чтобы повторно использовать его

Remy Lebeau 21.07.2023 07:36

@RemyLebeau Блими. Что бы эти люди ни думали дальше.

user207421 21.07.2023 07:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Как мне отключить клиента

Закрывая (closesocket()) подключенный сокет.

и правильно ли эта часть goto ждать другого клиента?

Вы не должны listen() снова, а вместо этого просто вернуться к accept() другому соединению. Но не используйте goto для этого. Вопреки некоторым советам и мнениям, которые вы можете заметить, goto иногда находит хорошее применение в C, но это не одно из них. Используйте петлю.

Обратите внимание, в Windows это closesocket() не close()

Remy Lebeau 21.07.2023 07:38

Я использую goto, потому что основная программа будет идти внутри while true, и я не могу поместить время, которое обрезает другое время посередине.

EnderMega 21.07.2023 21:24

Извини, @EnderMega, я этого не понимаю. Если вы используете goto для перехода в тело цикла, то это ужасно. Если вы прыгаете из одного места внутри цикла в другое, то вы можете использовать вложенный цикл. Однако вы можете обнаружить, что проще и понятнее разложить часть работы на отдельные функции.

John Bollinger 21.07.2023 21:32

Я имею в виду выпрыгнуть из петли.

EnderMega 22.07.2023 03:10

То, что вы сказали, сработало, только еще один вопрос: делает ли closesocket() так, что я не могу просто принять другого клиента? Или я могу closesocket() и ждать с accept() другого клиента?

EnderMega 22.07.2023 05:18

@EnderMega, прослушивающий сокет, с помощью которого вы принимаете соединения, отделен от подключенных сокетов, с помощью которых вы общаетесь с другими машинами. Каждая из них может быть закрыта, не затрагивая другую. Закрытие подключенного сокета не мешает приему дополнительных соединений через слушающий сокет. Закрытие прослушивающего сокета предотвратит прием каких-либо дополнительных подключений к нему, но не отключит существующие подключенные сокеты.

John Bollinger 22.07.2023 06:06

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