, потому что это игра, поэтому сервер запускается, когда первый клиент подключен к игре, и, если моя программа всегда будет ждать ввода других игроков, остальные подключенные игроки не могут играть, поэтому должен быть неблокирующим, асинхронным, если хотите.
Таким образом, вы хотите, чтобы по одному потоку на каждое клиентское соединение и всегда можно было принять новое клиентское соединение. Это звучит правильно.
В этом случае управление сообщениями, полученными от данного клиента, должно осуществляться в соответствующем потоке, а не в основном потоке. Основной поток только управляет клиентскими подключениями и запускает новые потоки, ему не нужно присоединяться к другим потокам.
Таким образом, accept выполняется в главном потоке, а не в разделенных потоках, и это дает сокету аргумент нового клиента при запуске нового потока для этого клиента, затем pthread_detach новый поток.
if ((serv->childpid = fork()) == 0) {
close(serv->sockfd);
всего этого не существует, fork нет, вы используете потоки.
Конечно, другой способ - вообще не использовать потоки, кроме fork , в любом случае роли между исходным процессом и дочерним процессом неизменны.
Ваш проблема в том, что вы не назначали нужные роли всем.