Как я могу сделать так, чтобы мой сервер имел открытые подключения к нескольким клиентам одновременно?

Я хочу написать свой собственный небольшой чат-сервер на C на машине MacOS. Теперь я хочу подключиться ко всем клиентам, которые находятся в сети, и позволить подключению открыться, чтобы иметь возможность получать и отправлять сообщения. Проблема в том, что я знаю только, как открыть одно сокетное соединение за раз. Так что пока может подключиться только один клиент, и болтать в таком виде довольно скучно;)

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
684
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Один из вариантов - использовать многопоточность с библиотекой pthreads. Другой вариант - использовать асинхронный ввод-вывод с вызовом select(2). С select(2) вы открываете кучу сокетов, а затем можете опросить каждый из них, чтобы узнать, есть ли в нем данные. Если в нем есть данные, вы их читаете, в противном случае вы переходите к следующему сокету.

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

gnud 05.12.2008 19:52

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

Попробуйте поискать в http://sourceforge.net несколько библиотек сэмплов.

Если все сделано правильно, вам понадобится только один номер порта. После того, как один клиент подключается к нему, он все еще может принимать другое подключение от другого клиента.

BCS 05.12.2008 10:13

Да, BCS - и это достигается с помощью метода, который я описал выше.

Bork Blatt 05.12.2008 11:44

Соединение с прослушивающим сокетом не установлено. Чтобы установить соединение, вам нужно принять его на другом сокете.

qrdl 05.12.2008 13:05

Bork, то, что ты говоришь, либо неясно, либо неверно. То, что вы написали, все еще звучит для меня так, как будто вы говорите, что вам нужно принять соединение на другом номере порта для каждого клиента, и я знаю, что это неправильно.

BCS 06.12.2008 01:22

взгляните на выбрать, pselect и голосование.

Я никогда не использовал их сам, но подозреваю, что они предназначены для того, что вы хотите делать.

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

Используйте select() или poll() для проверки входящих данных на всех открытых сокетах. Не забудьте включить прослушивающий сокет в список дескрипторов для select() - входящее соединение - это событие, которое обнаруживает select().

Это действительно очень просто. Никакого ракетостроения.

Поскольку Mac OS X основана на FreeBSD, для получения лучшей и наиболее эффективной программы вы должны использовать kqueue

вы также можете использовать fork-on-accept, например:

int listen_fd, new_fd;

while ((new_fd = accept(listen_fd, NULL, NULL)) != -1) {
    if (fork())
        close(new_fd);
    else
        // handle client connection
}
Ответ принят как подходящий

Самым простым решением для небольшого чат-сервера, вероятно, является использование select () или pselect ().

Взгляните на отличный Руководство Beej по сетевому программированию. В своем select () учебник он создает небольшой чат-сервер.

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