Я делаю программу чата сервер/клиент на 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 часть ждать другого клиента?
Ваш заголовок не соответствует вашему вопросу. Что касается вашего заголовка, это невозможно: отключенный сокет TCP нельзя использовать повторно. Что касается вашего вопроса, вы должны использовать close(). Вы также можете вызвать shutdown(), если знаете, почему вы это делаете, но вы должны использовать close() в любом случае. Вы не сохраняете результат recv() и не проверяете его на наличие ошибок. Вы не можете серьезно предлагать написать goto в наши дни, спустя 60 лет после того, как они были признаны вредными. Используйте петлю while и continue. Не пишите такой код. Вам нужно хорошенько взглянуть на достойный учебник по сети.
@user207421 user207421 «отключенный TCP-сокет нельзя использовать повторно» - на самом деле, в Windows это возможно, но только если вы используете DisconnectEx() с флагом TF_REUSE_SOCKET, а затем AcceptEx() (или ConnectEx()), чтобы повторно использовать его
@RemyLebeau Блими. Что бы эти люди ни думали дальше.





Как мне отключить клиента
Закрывая (closesocket()) подключенный сокет.
и правильно ли эта часть goto ждать другого клиента?
Вы не должны listen() снова, а вместо этого просто вернуться к accept() другому соединению. Но не используйте goto для этого. Вопреки некоторым советам и мнениям, которые вы можете заметить, goto иногда находит хорошее применение в C, но это не одно из них. Используйте петлю.
Обратите внимание, в Windows это closesocket() не close()
Я использую goto, потому что основная программа будет идти внутри while true, и я не могу поместить время, которое обрезает другое время посередине.
Извини, @EnderMega, я этого не понимаю. Если вы используете goto для перехода в тело цикла, то это ужасно. Если вы прыгаете из одного места внутри цикла в другое, то вы можете использовать вложенный цикл. Однако вы можете обнаружить, что проще и понятнее разложить часть работы на отдельные функции.
Я имею в виду выпрыгнуть из петли.
То, что вы сказали, сработало, только еще один вопрос: делает ли closesocket() так, что я не могу просто принять другого клиента? Или я могу closesocket() и ждать с accept() другого клиента?
@EnderMega, прослушивающий сокет, с помощью которого вы принимаете соединения, отделен от подключенных сокетов, с помощью которых вы общаетесь с другими машинами. Каждая из них может быть закрыта, не затрагивая другую. Закрытие подключенного сокета не мешает приему дополнительных соединений через слушающий сокет. Закрытие прослушивающего сокета предотвратит прием каких-либо дополнительных подключений к нему, но не отключит существующие подключенные сокеты.
Вы делаете прослушивание ровно один раз. Затем вы принимаете каждое соединение, и когда вы закончите, вы можете закрыть его и вернуться к принятию.