Лучшая практика: держать TCP / IP-соединение открытым или закрывать его после каждой передачи?

мой сервер-приложение использует TIdTCPServer, несколько клиентских приложений используют TIdTCPClients для подключения к серверу (все компьютеры находятся в одной локальной сети).

некоторым из клиентов нужно только связаться с сервером каждые пару минут, другие раз в секунду, и один будет делать это около 20 раз в секунду.

Если я сохраню соединение между клиентом и сервером открытым, я сохраню повторное соединение, но должен проверить, потеряно ли соединение.

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

каков наилучший способ сделать это?

на какой частоте передачи данных я должен держать соединение открытым в целом?

каковы другие преимущества / недостатки для обоих сценариев?

7 ответов


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


два цента от эксперимента...

мое первое приложение TCP/IP client / server использовало новое соединение и новый поток для каждого запроса... лет назад...

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

У меня даже были некоторые проблемы с подключением с большим количеством запросов concurent: У меня не было достаточно портов на моем сервере!

Так я переписал его, следуя схеме HTTP/1.1, и KeepAlive характеристика. Он намного эффективнее, использует небольшое количество потоков, а ProcessExplorer нравится мой новый сервер. И у меня больше никогда не кончается портвейн. :)

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

короче говоря: если вы можете, сохраните клиентские соединения для некоторых протокол.


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

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

Я бы склонялся к сохранению одного соединения открытым в большинстве корпоративных приложений. Это, как правило, приведет к более чистому коду, который легче поддерживать.

/twocents


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

Вам также нужно думать о будущем, есть ли шанс, что в будущем вам понадобятся соединения, которые будут оставлены открытыми? если так, то вы сами ответили на свой вопрос.

я реализовал чат-систему для проекта, в котором ~50 человек (число растет с каждым 2 месяцем) всегда подключен и помимо чата он также включает в себя передачу данных, манипуляции с базой данных с помощью определенных команд и т. д. Моя реализация сохраняет соединение с сервером открытым с момента запуска приложения до тех пор, пока приложение не будет закрыто, никаких проблем до сих пор, однако, если соединение потеряно по какой-то причине, оно автоматически восстанавливается и все продолжается безупречно.

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


Если вы не масштабируетесь до многих сотен параллельных подключений, я определенно буду держать его открытым - это намного лучше двух вариантов. Как только вы масштабируете сотни в тысячи параллельных подключений, вам может потребоваться удалить и снова подключиться. Я построил всю свою структуру вокруг этого (http://www.csinnovations.com/framework_overview.htm) поскольку это позволяет мне "толкать" данные клиенту с сервера, когда это необходимо. Вам нужно написать немного код, чтобы гарантировать, что соединение работает и работает (сетевые выпадающие списки, временные пинги и т. д.), Но если вы делаете это в своей "структуре", то ваш код приложения может быть написан таким образом, что вы можете предположить, что соединение всегда "вверх".


проблема заключается в ограничении потоков для каждого приложения, около 1400 потоков. Таким образом, Макс 1300 клиентов подключены в то же время +-.


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