Создание многопоточного сервера TCP / IP - PullRequest
10 голосов
/ 18 февраля 2010

Я хочу создать сервер TCP / IP, который будет использоваться до 100 одновременными клиентами, но все еще не знаю, с чего начать.

по крайней мере мне нужен сервер для этого:

  1. Прослушивание клиента и сохранение всех их в массиве или списке.
  2. для каждого клиента необходимо получать и отправлять данные в зависимости от статуса клиента.
  3. Сервер должен обновлять список клиентов, когда кто-то подключается или отключается.
  4. Предпочитают работать как сервис с графическим интерфейсом для управления им.

Может ли кто-нибудь помочь, как начать с этого, я посмотрел пример indy, но они не помогли, также посмотрел большинство компонентов, но все еще ищет.

Ответы [ 7 ]

8 голосов
/ 18 февраля 2010

Вам нужно использовать TidTCPServer, который является многопоточным внутри.Вам не нужно управлять потоками.Все прозрачно, поэтому то, как вы пишете приложение для одного клиента, (почти) так же, как вы пишете его для многих.Смотрите событие OnConnect.Существует параметр TidContext, внутри которого есть TThreadList.Вы можете использовать это событие, чтобы «зарегистрировать» / добавить своих клиентов в свой собственный массив / список и OnDisconnect, чтобы удалить клиентов.

Событие OnExecute инициируется, когда сервер получает сообщение.Используйте его параметры для чтения отправленного сообщения.

Также вам необходимо другое приложение , которое будет вашим клиентом, используя TidTCPClient.В этом приложении вы установите адрес вашего сервера (см. Свойство Host), а также порт, который должен совпадать с адресом сервера.Вы должны вызвать Connect (когда сервер работает) и для отправки строк у вас есть метод SendCmd.(Также см. IOHandler.WriteLn, если хотите)

Есть и другие вещи, но я думаю, этого достаточно, чтобы вы начали.Также вы можете публиковать сообщения на форумах Embarcadero на форуме .Delphi.Winsock, на котором плавают члены команды Indy.Или, может быть, вы можете спросить прямо в .Delphi.Non-Technical, и парни там помогут вам.

Другой подход - DataSnap , который является более объектно-ориентированным слоем по сравнению с Indy (не дляпутать с DBX), который дает JSON, REST и другие вкусности.Смотрите небольшой обзор здесь .

3 голосов
/ 18 февраля 2010

И еще одним вариантом библиотеки Delphi будет synapse , который обеспечивает простую структуру, которую можно легко расширить. В предоставленных файлах доступна демонстрация IOCPPool , которая может оказаться полезной.

Synapse - это скорее структура классов, чем библиотека компонентов. Существует активное и активное сообщество пользователей, которое готово поддержать любые проблемы. Я использую эту библиотеку в Delphi 2010 без каких-либо проблем (хотя я использую последнюю версию разработки из SVN).

Поскольку они не являются компонентами, очень просто использовать классы в простых консольных приложениях или службах Windows.

3 голосов
/ 18 февраля 2010

На платформе Windows, вероятно, лучше избегать select для большого количества одновременных подключений (хотя 100 - это не большое количество подключений). Тем не менее, avirtuos является верным в том смысле, что вы хотите избежать любых моделей «поток на соединение». Наиболее эффективный подход в Windows - это использование перекрывающихся портов ввода-вывода и портов завершения ввода-вывода. Это позволяет вам управлять десятками тысяч соединений с небольшим количеством потоков (возможно, 2 или 3).

У меня нет опыта работы с Delphi, поэтому я понятия не имею, насколько легко взаимодействовать с кодом C ++, НО у меня есть бесплатная серверная среда порта завершения ввода-вывода C ++ (доступна по адресу здесь ) это, по крайней мере, покажет вам, как работает стандартный Win32 I / O Completion Port API. Это может быть полезно для вас, и вы можете сделать что-то подобное в Delphi.

2 голосов
/ 19 февраля 2010

Indy - ваш лучший выбор: 1000 клиентов не так уж много: я разработал сервер, который должен был обслуживать 4-5 тыс. Клиентов, и он работает как шарм.

  1. Прослушивание клиента и сохранение всех их в массиве или списке. + 3. Сервер должен обновлять список клиентов, когда кто-то подключается или отключается.

-> Что касается списка клиентов, вы можете перебрать элемент TThreadList в TidTCPServer (версия 9.0), в котором хранятся все «живые» потоки, каждый поток «эквивалентен» клиентскому соединению, хотя потоки могут пережить подключение клиента, но вы можете это исправить, установив соответствующее значение тайм-аута подключения. Если вы хотите, вы также можете поддерживать свой собственный Список клиентов (например, наследовать от TList или создать Generics.Collection): вы добавили бы информацию о клиенте после события onConnect (класс tidPeerThread предоставляет всю клиентскую информацию: IP ...)

Затем вы периодически просматриваете этот список, проверяете наличие живых соединений (например, команда ping) и убиваете / удаляете всех зомби.

[документация indy] Обработчик событий для попыток подключения к одноранговому потоку.

свойство OnConnect: TIdServerThreadEvent;

Описание

OnConnect - обработчик событий для TIdServerThreadEvents. OnConnect возникает, когда TIdPeerThread пытается подключиться к TIdTCPServer.

OnConnect получает AThread в качестве параметра, представляющего поток TIdPeerThread, запрашивающий соединение.

Назначьте процедуру-обработчик события TIdServerThreadEvent для OnConnect. [/ документация indy]

  1. для каждого клиента, он должен получать и отправлять данные в зависимости от статуса клиента: -> проверьте исходный код демо-версии чата и сервера для подробного примера.

  2. Предпочитаете работать как сервис с графическим интерфейсом для управления им: вы можете разработать сервисное приложение, которое будет регистрировать всю свою активность в БД, и второе приложение, которое будет обращаться к этой базе данных и отображать всю доступную статистику (номер клиента). ...).

и вот ссылки на Indy 9.0 (источники и документация): http://www.indyproject.org/downloads/Indy_9_00_14_src.zip http://www.indyproject.org/downloads/Indy-9-0-Help-WinHelp.zip

А вот книга Indy, хотя я не думаю, что она понадобится вам после прочтения документации: Indy подробно: http://www.atozed.com/Indy/Book/index.EN.aspx

Ищите здесь хороший урок: http://www.devarticles.com/c/a/Delphi-Kylix/Creating-Chat-Application-with-Borland-DelphiIndy-The-Client/

Удачи

1 голос
/ 18 февраля 2010

100 розеток не так много. Вы можете пойти на все проблемы с использованием чего-то вроде epoll (), но для этого случая я просто настрою один FD_SET со всеми сокетами, select () на весь набор, затем проверим каждый и обработаю их в последовательность. Если бы мне пришлось сделать что-то, что могло бы занять много времени, я бы использовал пул потоков для обработчиков сообщений.

0 голосов
/ 18 февраля 2010

Некоторые отличные наборы компонентов, которые полезны для таких ситуаций, как ваша (и многие другие): кБмМВт и RemObjects .Я думаю, что есть и другие хорошие наборы, вы можете выполнить поиск в архиве или задать вопрос в новостной группе Delphi thirdpartytools Embarcaderos.Вы можете искать архивы здесь: http://codenewsfast.com/

0 голосов
/ 18 февраля 2010

Я недавно столкнулся с этой проблемой. Вот ссылка на пример C ++, использующий EPOLL для управления сотнями сокетов многоадресной рассылки. У вас будет TCP / IP, но это просто простое изменение.

Какой бы метод вы ни выбрали, для 100+ одновременных сокетов / клиентов вы захотите использовать модель потока, которая опирается на опрос, выбор или предпочтительный epoll, если ваша платформа поддерживает его.

http://anthonyvirtuoso.com/public/dokuwiki/doku.php/projects:multiplexreceiverepoll

@ jfawcett - выбор на более чем ~ 50 FD имеет довольно значительный удар по процессору в зависимости от того, как часто вы фактически выполняете выбор. В моем комментарии выше этот пример класса изначально использовал select, но после просмотра стоимости процессора (valgrind w / callgrind) я переключился на epoll. Но, безусловно, выберите правильный вариант.

...