|
5 / 5 / 3
Регистрация: 14.11.2016
Сообщений: 94
|
||||||
Эхо-сервер с неблокирующим сокетом13.09.2017, 23:10. Показов 9467. Ответов 7
Метки нет (Все метки)
Здравствуйте, уважаемые форумчане. Пишу эхо-сервер, основной функционал работает, но нужно сделать его неблокирующим, для обслуживания множества клиентов. Делаю после создания слушающего сокета fcntl(listener, F_SETFL, O_NONBLOCK) и после клиентского в главном цикле
fcntl(acsoc, F_SETFL, O_NONBLOCK)- при запуске (если порт не занят конечно) выдает через perror ошибку Resource temporarily unavailable, также не показывает в консоли сообщение о доступности сервера на порту (порт выбирается из диапазона 50000 - 55000). Порт задается в качестве параметра при запуске сервера, либо идет по умолчанию, и если он занят - сервер автоматически подбирает из диапазона свободный порт
0
|
||||||
| 13.09.2017, 23:10 | |
|
Ответы с готовыми решениями:
7
Работа с неблокирующим сокетом в Linux Комментарии к коду эхо-клиент/эхо-сервер консоль эхо сервер |
|
Почетный модератор
11559 / 4353 / 453
Регистрация: 12.06.2008
Сообщений: 12,455
|
|
| 13.09.2017, 23:35 | |
|
Странно всё сделано... сокеты сделаны неблокируемыми, а работаете с ними как с блокируемыми. Например, если посмотрите описание функции accept(), то там сказано, что если сокет неблокируемый и ещё нет запроса от клиента на подключение, то функция accept() не будет блокироваться, сразу вернёт -1 и выставит errno в значение EAGAIN. Это означает, что ошибки не было, просто никто не пытается подключиться к серверу. Поэтому у вас код сразу попадёт на perror("AcceptError") и завершится. Тоже самое касается и recv().
Вообще, можно не делать сокет неблокируемым, а использовать функции select/poll/epoll (для данной задачи я рекомендую epoll, т.к. там легко добавлять/удалять отслеживаемые сокеты), что бы ожидать какого-либо события от сокета, а не грузить процессор пустым циклом. Кстати, весь ваш код заточен только под один клиент. Функция accept() не вызовется, пока не закроется предыдущее соединение с клиентом. Т.е. клиенты будут подключаться только по-очереди. И фактически алгоритм остаётся блокируемым. Предлагаю сразу после listen() добавить listener в отслеживание через epoll. А в цикле запускать epoll_wait() и если он вернёт > 0 (т.е. произошло событие на каком-то сокете), то сравнить сработавший event.fd с listener. Если совпадает, то делаем accept() и новый сокет добавляем к epoll. Если не совпал, значит, это какой-то из ранее подключившихся клиентов прислал пакет и мы его просто принимаем через recv(). Если recv() вернул 0, значит клиент отключился, делаем close() и удаляем сокет из epoll. В этом случае даже не нужно хранить список клиентов в явном виде... всё хранится внутри epoll.
1
|
|
|
5 / 5 / 3
Регистрация: 14.11.2016
Сообщений: 94
|
||||||
| 14.09.2017, 23:32 [ТС] | ||||||
|
Насчёт заточки под один клиент. А если я сделаю динамический массив дескрипторов сокетов и calloc' ом выделю память под необходимое количество подключений и в главном цикле сделаю цикл где для каждого элемента массива буду делать accept ? Мне бы понять как с селектом тут решить
Добавлено через 1 час 4 минуты Для иллюстрации немного изменил код, тут для 3-х подключений
0
|
||||||
|
Почетный модератор
11559 / 4353 / 453
Регистрация: 12.06.2008
Сообщений: 12,455
|
||||||
| 15.09.2017, 01:21 | ||||||
|
Как-то сложно на мой взгляд... да и обрабатывать массив подключений неудобно. Предлагаю такой вариант:
И не забывайте обрабатывать ошибки... иначе что-то будет глючить и вы даже не поймёте, что именно.
1
|
||||||
|
153 / 148 / 66
Регистрация: 20.02.2014
Сообщений: 556
|
|
| 15.09.2017, 17:54 | |
|
Knyaz_Myshkin, а вообще по поводу неблокируемых сокетов: в линухе есть специальный вызов accept4(), который с флагом SOCK_NONBLOCK возвращает новый сокет в нон-блокед режиме.
0
|
|
|
5 / 5 / 3
Регистрация: 14.11.2016
Сообщений: 94
|
|
| 16.09.2017, 17:05 [ТС] | |
|
Humanoid, Спасибо за вариант, обязательно его опробую. Только у меня требуется именно через select сделать, задача такая). Смотрю примеры не очень понятно
0
|
|
|
Почетный модератор
11559 / 4353 / 453
Регистрация: 12.06.2008
Сообщений: 12,455
|
||||||||||||||||
| 16.09.2017, 23:58 | ||||||||||||||||
Сообщение было отмечено Knyaz_Myshkin как решение
Решение
Я бы рекомендовал почитать какую-нибудь книгу. Лично я читал только Роберт Лав "Системное программирование Linux" - там очень хорошо всё объясняется. Всех тонкостей не помню, но смысл расскажу. Функция select() ищет среди указанных файловых дескрипторов те, у который случились события (нас интересуют только входящие события - например, получены данные). Описана функция так:
readfds - список файловых дескрипторов, у которых мы отслеживаем события чтения. writefds - тоже самое, но события записи. Например, когда запись файл или передача по сети завершилась. exceptfds - тоже самое, но события ошибок. timeout - максимальное время ожидания событий. Аргументы readfds, writefds и exceptfds имеют тип fd_set. По сути дела, этот тип представляет собой массив переменных типа long общим размером 1024 бита (32 элемента на 32-битных системах и 16 элементов на 64-битных). Правильнее это значение брать из константы FD_SETSIZE. Можно рассматривать этот тип как одно 1024-битное (FD_SETSIZE-битное) число. Если установлен только десятый бит, значит событие ожидается от файлового дескриптора, равного 10. Если установлен ещё и 125-ый бит, то и файловый дескриптор с номером 125 так же будет отслеживаться. Для установки/снятия битов есть макросы: FD_SET(fd, fdsetp) - устанавливает бит с номером fd... т.е. файловый дескриптор будет отслеживаться функцией select. FD_CLR(fd, fdsetp) - снимает бит. FD_ZERO(fdsetp) - очищает все биты. FD_ISSET(fd, fdsetp) - проверяет, установлен ли бит. Возвращает true, если установлен или false, если нет. Если мы хотим отслеживать возможность чтения файловых дескрипторов с номерами 5, 12, 6 и 8, то нам надо выполнить
В общем, та же самая программа, но переделанная на select()
1
|
||||||||||||||||
|
5 / 5 / 3
Регистрация: 14.11.2016
Сообщений: 94
|
|
| 17.09.2017, 22:23 [ТС] | |
|
Humanoid, Покорнейше благодарю, и за полезную информацию и за код))
0
|
|
| 17.09.2017, 22:23 | |
|
Помогаю со студенческими работами здесь
8
Параллельный эхо-сервер Научите создавать эхо сервер SIP - телефон: эхо сервер
Совместимость процессора с 478 сокетом и материнской платы с 479 сокетом Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие.
Ссылка в Linux — это дополнительная запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая. . .
|
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ВВЕДЕНИЕ
Выполняя задание на управление насосной группой заполнения резервуара,. . .
|
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
|
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога
Финальные проекты на Си и на C++:
hello-sdl3-c. zip
hello-sdl3-cpp. zip
Результат:
|
|
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога
MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
|
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд.
Даже если у вас. . .
|
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает
монорепозиторий в котором находятся все исходники.
При создании нового решения, мы просто добавляем нужные проекты
и имеем. . .
|
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение:
В этой книге («Подход, основанный на вариантах использования») Ивар утверждает,
что архитектура программного обеспечения — это
структуры,. . .
|