Сервер C# - эффективность сокетов TCP/IP

Добрый день всем!

Я работаю на сервере с открытым исходным кодом для игры с закрытым исходным кодом - игра работает с использованием сокетов TCP/IP (вместо UDP, доу...). Так что, будучи протоколом на основе соединений, я не могу работать с этим.

Моя текущая структура программы (неактивна):

Основная нить

  • Получите новое соединение и создайте новый объект клиента.

Клиентский объект

  • IOloop (работает в собственном потоке)

    • Получать данные из сокета, обрабатывать пакеты. (один пакет за раз)
    • Отправка данных из других потоков (по одному пакету за раз)

Клиент отправит данные немедленно (без задержки), когда это его собственный поток.


Я заметил огромный недостаток программы, в основном она отправляет данные очень медленно. Потому что я отправляю пакет данных за пакетом, синхронно. (Socket.Send(byte[] buffer))

Я хотел бы отправить данные практически сразу, без задержки - асинхронно.

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

Моя текущая система использует синхронную отправку с отключенным алгоритмом Nagle - но в этом есть недостаток узкого места - отправьте один пакет, отправьте блоки операций до подтверждения TCP, затем отправьте следующий... Я могу легко выдавать 10 пакетов каждые 100 мс, и если отправка пакетов занимает 400 мс, резервное копирование и разрывы. Конечно, на моем локальном хосте я не вижу этой проблемы.


Итак, мой вопрос: как лучше всего отправить несколько небольших пакетов данных? Я имею в виду объединение данных для отправки в конце каждого цикла потока ввода-вывода в один большой байтовый буфер, чтобы уменьшить задержку туда и обратно - но очевидная проблема здесь заключается в том, что это подрывает избегание алгоритма Nagle, которое, как я надеялся, остановит задержки.

Как работает синхронная отправка? Как я полагаю, он блокируется до тех пор, пока получатель не подтвердит правильность полученных данных? Есть ли способ сделать это, не дожидаясь подтверждения? Я понимаю, что все пакеты должны идти в порядке и правильно (согласно спецификации протокола).

1 ответ

Я провел некоторые исследования и сейчас использую текущую систему:

Асинхронные операции отправки / получения без потоков, используя AsyncCallbacks.

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

Этот метод значительно снижает системные издержки - пулы потоков, память и т. Д.

Я использовал несколько методов из следующих и настроил по своему вкусу: https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx

Очень эффективно, очень рекомендую этот подход. Для любого сетевого приложения TCP/IP низкая задержка очень важна, и асинхронные обратные вызовы - лучший способ сделать это.

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