Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > TCP сервер на большое число клиентов


Автор: Mikel 10.10.2009, 14:20
Господа! Ситуация такая: есть сервер с базой данных, есть несколько тысяч клиентов, которые коннектятся к нему и ждут. Клиенты работают с БД ч/з сервер, при изменении базы данных сервер информирует клиентов об изменениях.
Сейчас сервер сделан на TWSocketServer из пакета FPiette (ICS). Есть проблемы: при числе клиентов порядка тысячи перестает принимать соединения.
Подскажите, пожалуйста, как лучше реализовать подобный сервер. Нужна ли многопоточность, если клиенты в основном не проявляют сетевой активности, разве что при редактировании и когда принимают изменения.

Автор: Virtuals 10.10.2009, 14:52
Mikel, на какой операционке сервер? есть подозрение что ограничение самих виндов...

Автор: Mikel 10.10.2009, 15:08
Сервер на Windows'e. Пробовал на XP x64 и на серверной 2003

Может стоит переписать на многопоточный сервер на Indy?

Автор: kami 12.10.2009, 13:28
Цитата(Mikel @  10.10.2009,  15:08 Найти цитируемый пост)
Может стоит переписать на многопоточный сервер на Indy?

Не стоит. Несколько тысяч потоков - это не очень хорошо для ОС.

Цитата(Virtuals @  10.10.2009,  14:52 Найти цитируемый пост)
есть подозрение что ограничение самих виндов...

Вряд ли. Сейчас совершенно спокойно создал 2000 соединений вместе с сопутствующими структурами для приема/передачи данных (в смысле - 2000 исходящих и соответственно 2000 входящих) на основе TClient|TServerSocket (обертки работы с ними где-то здесь уже выкладывал).
Вернее, не совсем спокойно - после первой тысячи соединений машинка поднапряглась на создании, но в процессе сетевого обмена со всеми клиентами вела себя более чем адекватно. (Vista Home Premium).

Добавлено через 2 минуты и 25 секунд
А вот отфутболивать соединения может из-за ограничения на количество полуоткрытых соединений (в TCPView от Sysinternals такие соединения идут под флагом SYN_SENT). Afair, их по умолчанию разрешается не более 100.

Автор: Mikel 12.10.2009, 13:55
В Indy 10  в одном потоке с помощью 'fibers' можно работать с несколькими сокетами, т.е. например открыть 1000 потоков в которых могут работать 2000 клиентских сокетов, по 2 на поток.

Вообще тест проводил так- соединяются несколько сотен клиентов, но они у меня находятся в одном потоке, т.е. сначала идет соединение всех сокетов, потом отправка регистрационных данных и т.д. Так вот получается что если пытаться подсоединить, например 300 клиентов разом, то сервер выдает ошибку о перегрузке стека.

Автор: MetalFan 12.10.2009, 17:01
имхо стоит почитать про порты завершения... где-то даже толковая статейка попадалась.
искать по: "порты завершение" "IO Completion Port" "IOCP"

Автор: kami 12.10.2009, 17:01
Цитата(Mikel @  12.10.2009,  13:55 Найти цитируемый пост)
В Indy 10  в одном потоке с помощью 'fibers' можно работать с несколькими сокетами

Не работаю с Indy, у меня на них аллергия smile Поэтому ничего плохого, а равно и хорошего про них не скажу, ни про какую версию.

Цитата(kami @  12.10.2009,  13:28 Найти цитируемый пост)
отфутболивать соединения может из-за ограничения на количество полуоткрытых соединений 

Ошибся - в интернете говорят, что WinServer2003 не имеет этого ограничения.

Цитата(Mikel @  12.10.2009,  13:55 Найти цитируемый пост)
сначала идет соединение всех сокетов, потом отправка регистрационных данных и т.д. 

Раз в одном потоке - не пробовал перед/после каждого Connect делать Application.ProcessMessages (или аналог, если это доп.поток)? В проведенном мной тесте без ProcessMessages подключения "загнулись" на сто_каком_то с ошибкой WSAECONNREFUSED.

Автор: MetalFan 12.10.2009, 17:04
ага...  вот и статейка на http://www.gamedev.ru/community/mmorpg/articles/?id=2522

Автор: Mikel 13.10.2009, 16:29
MetalFan, благодарю, ознакомлюсь smile


kami, я думаю как раз в этом то и проблема, то что он не выполнив до конца обработчик одного сокета берется за другой и из-за этого и происходит переполнение стека...

Автор: Mikel 20.10.2009, 10:03
Сделал на Indy- вообще не катит smile Потоки медленно все же создает, а после тысячи потоков вообще несколько секунд ухаодит на создание потока.

Поставил ProcessMessages в обработчики старого сервера на ICS, теперь 100%ый коннект. Ограничения на соединения кстати есть, но не на сервер- с одного компьютера почти 4000 соединения на сервер можно открыть, потом не соединяется, после чего можно законнектиться еще 4000 сокетов с другого компьютера. В общем  соединений держит точно.
Но есть еще вопрос, оповещение об изменении происходит в цикле, где в каждый сокете высылается пакет информации об изменении. Так вот когда их много, опять перегружается стек. Может где-то еще впихнуть ProcessMessages? smile

Кстати еще один вопрос- компьютер под сервер все же двухядерник, а в ICS, как я понимаю, все обрабатывается в одном потоке, нужно ли как-то оптимизировать его под систему с несколькими процессорами?

Автор: MetalFan 21.10.2009, 18:19
ээээ... я может чего не понял. но при чем тут потоки и ProcessMessages????

Автор: Mikel 22.10.2009, 07:41
Прошу прощения, наверное не совсем корректно выразился, первое предложение относилось к Indy, а остальное- вернулся к старому серверу, на ICS, который работает на асинхронных сокетах.

Автор: dumb 22.10.2009, 08:42
Цитата(Mikel @  20.10.2009,  11:03 Найти цитируемый пост)
Сделал на Indy- вообще не катит smile Потоки медленно все же создает, а после тысячи потоков вообще несколько секунд ухаодит на создание потока.
не совсем понятно, причем тут Indy. у индейцев есть своя более или менее нормальная реализация серверных сокетов(IdTCPServer,etc) с пулом потоков.
а создавать руками тысячами потоки - по-любому плохая, негодная идея.

Цитата(Mikel @  20.10.2009,  11:03 Найти цитируемый пост)
Поставил ProcessMessages в обработчики старого сервера на ICS
и теперь ошибки старой реализации замаскированы ценой тормозов у клиентов.
Цитата(Mikel @  20.10.2009,  11:03 Найти цитируемый пост)
в каждый сокете высылается пакет информации об изменении. Так вот когда их много, опять перегружается стек.
естественно, надо не во все разом "палить", а рассылать "кучками". и, похоже, что ты не проверяешь коды возвратов(send или его ics-"оберток") и состояние сетевого стека.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)