Сервер TCP с несколькими клиентами C-код

Я написал приложение TCP-сервера в C-коде, которое может одновременно обрабатывать несколько клиентских подключений. Когда сервер получает данные от одного клиента, все клиенты должны его получить. Я использовал select (), чтобы создать соединение между сервером и несколькими клиентами, но я не знаю, как сделать так, чтобы все клиенты получали одни и те же данные одновременно, и каждый из них мог отправлять данные в сервер.

read_option (fd) - моя функция, используемая в приложении

while(1)
{
    select (nfds+1, &readfds, NULL, NULL, &tv);
    if (FD_ISSET (sd, &readfds))
    {
        len = sizeof (from);
        bzero (&from, sizeof (from));
        client = accept (sd, (struct sockaddr *) &from, &len);
        if (client < 0)
        {
            continue;
        }
        if (nfds < client) 
            nfds = client;
        FD_SET (client, &actfds);
        fflush (stdout);
    }
    for (fd = 0; fd <= nfds; fd++)  
    {
        if (fd != sd && FD_ISSET (fd, &readfds))
        {
            if (read_option(fd))
            {
                fflush (stdout);
                close (fd);
                FD_CLR (fd, &actfds);
            }
        }
    }
1
nl ja de
Вы должны подумать о том, что называется многоадресной рассылкой, но вы должны быть осторожны. Если вам это не нравится, вы можете просто реализовать что-то более наивное, сервер отправит каждому клиенту все, что он получит. Это означает, что вы храните IP-адреса своих клиентов на карте или массиве.
добавлено автор ipinak, источник

1 ответы

Если вы хотите отправлять и получать от нескольких клиентов одновременно - по крайней мере, для стороны приема - вам нужно будет использовать потоки, так как все ваши клиенты могут отправлять данные на ваш сервер одновременно, а пакеты каждого клиента - необходимо будет обрабатывать отдельно. (Я предполагаю, что данные, полученные в «read_option», составляют более нескольких байтов, и для обработки требуется более нескольких микросекунд - если это предположение неверно, то вы можете делать то, что делаете сейчас, но я «Я уверен, что это EASIER, чтобы решить это, используя потоки». Очевидно, что, если у вас есть достаточное количество клиентов, у вас может не хватить пропускной способности центрального процессора или сети, чтобы обрабатывать все пакеты за определенный промежуток времени.

Возможно одновременное использование многоадресной рассылки для всех клиентов, но вы не можете гарантировать, что все клиенты будут получать данные одновременно, - конечно же, если мы говорим о времени компьютера одновременно. Если клиенты находятся в той же сети, что и сервер, и если мы говорим о человеческом времени реакции (0,05-0,1 с), то, возможно, вы можете это достичь. Если машины распределены по всему интернету, вы должны быть довольны достижением 0,1-0,5 с - и, возможно, хуже.

Итак, учитывая комментарии:

Поскольку вы выполняете send() и receive() в read_option() , ваш read_option будет блокироваться в этот момент, поэтому любой другой клиент будет не обрабатываться.

Вам, по существу, нужно будет начать поток для каждого клиента, используя pthread_create() . Затем вы можете «общаться» между сервером и каждым из клиентов независимо друг от друга. Я ожидаю, что вам также понадобится какая-то синхронизация между каждым потоком, чтобы они не бегали впереди друг друга, или некоторые из них. Поскольку я не знаю, в какую игру вы играете, я не уверен, что такое «правила игры», и не могу прокомментировать это. На самом деле, я думаю, что это отличный вопрос для другого вопроса, скорее чем в этом вопросе [в противном случае, я боюсь, что это никогда не закончится!]

1
добавлено
Для двух игроков, считая, что вы не играете в шахматы или некоторые такие, я бы сказал, что делать то, что вы делаете прямо сейчас, хорошо.
добавлено автор Mats Petersson, источник
Но если вы хотите использовать потоки, посмотрите, например, «pthreads».
добавлено автор Mats Petersson, источник
Вы уверены, что хотите закрыть (fd); в середине цикла? Не говорю, что все происходит неправильно, но это может быть ... Помимо этого, я думаю, нам нужно посмотреть, что делает read_option.
добавлено автор Mats Petersson, источник
Хорошо, я отредактирую сообщение, чтобы объяснить немного больше о потоках.
добавлено автор Mats Petersson, источник
Я подозреваю, что вы можете разобраться в синхронизации, если клиент ждет следующего перехода от другого пользователя. И я также не думаю, что время критическое. Конечно, вам нужно будет отправить изменения на плату для обоих клиентов, что, вероятно, потребует немного комм между клиентами, но вы можете решить это несколькими способами.
добавлено автор Mats Petersson, источник
Как использовать потоки? Моему приложению нужны только два клиента (речь идет об игре, и каждый игрок должен увидеть настольную игру и ходы другого игрока. Игра реализована в этой функции «read_option»)
добавлено автор Roxana, источник
В этот момент только первый клиент, который запустил игру, может общаться с сервером (данные приема-передачи и приложение работают «отлично», потому что первый клиент может играть так, как есть 2 игрока), а второй клиент не делает не получают ничего, кроме игры основного меню, и не видят действия, которые сделали первый.
добавлено автор Roxana, источник
close (fd) используется для закрытия соединения после выполнения функции read_option (fd), но я хочу, чтобы все fd имели результат. Функция слишком длинная, чтобы опубликовать ее здесь, но в ее коде все данные отправки/получения между клиентом (с дескриптором fd) и сервером
добавлено автор Roxana, источник
Я понимаю. Это касается игры с чертами. Я буду искать, как использовать эти pthread_create (). Я новичок в программировании сервера/клиента в C, но я надеюсь решить эту проблему. Большое спасибо.
добавлено автор Roxana, источник