Есть ли веская причина не использовать TcpListener
для реализации высокопроизводительного/высокопроизводительного сервера TCP
вместо SocketAsyncEventArgs
?
Я уже реализовал этот высокопроизводительный/высокопроизводительный TCP-сервер, используя SocketAsyncEventArgs
, прошел через всевозможные головные боли при обработке этих закрепленных буферов, используя большой предварительно выделенный массив byte
и пулы SocketAsyncEventArgs
для приема и получения, собирая вместе с помощью некоторых низкоуровневых вещей. и блестящий интеллектуальный код с некоторым потоком данных TPL и некоторым Rx, и он работает отлично; почти учебник в этом начинании - на самом деле я узнал более 80% этих вещей из чужого кода.
Однако есть некоторые проблемы и опасения:
- Сложность: я не могу делегировать какие-либо изменения на этом сервере другому члену команды. Это привязывает меня к такого рода задачам, и я не могу уделять достаточно внимания другим частям других проектов.
- Использование памяти (закрепленные
byte
массивы): при использованииSocketAsyncEventArgs
пулы должны быть предварительно выделены. Таким образом, для обработки 100000 одновременных подключений (хуже, даже на разных портах) там бесполезно зависает большая куча оперативной памяти; предварительно распределены (даже если эти условия выполняются только несколько раз, сервер должен быть в состоянии обрабатывать 1 или 2 таких пика каждый день). TcpListener
на самом деле работает хорошо: я действительно протестировалTcpListener
(с некоторыми уловками, такими как использованиеAcceptTcpClient
в выделенном потоке, а не не версияasync
, а затем отправка принятых подключений вConcurrentQueue
и не создаватьTask
на месте и т.п.) и с последней версией .NET он работал очень хорошо, почти так же хорошо, какSocketAsyncEventArgs
, без потери данных и с низким объемом памяти, что помогает не тратить слишком много ОЗУ на сервере и предварительное выделение не требуется.
Так почему же я нигде не вижу, чтобы TcpListener
использовалось, а все (включая меня) используют SocketAsyncEventArgs
? Я что-то упускаю?
3.
, я делаю именно то, что вы говорите! Прием происходит в простом цикле на выделенномThread
(Task
создан с опциейTaskCreationOptions.LongRunning
). - person Kaveh Shahbazian   schedule 03.01.2015SocketAsyncEventArgs
приводит к закреплению буфера массиваbyte
, поэтому не может быть эффективно собран мусор и вызывает фрагментацию памяти, что приводит к более высокому использованию ЦП и ОЗУ; плюс все дополнительные препятствия, которые необходимо преодолеть, чтобы подготовить и управлять пуламиSocketAsyncEventArgs
объектов; в целом требуется гораздо больше дополнительной работы и обслуживания, и, что более важно, эти знания/опыт не могут быть легко/безопасно/надежно переданы другому разработчику. - person Kaveh Shahbazian   schedule 03.01.2015TcpListener
обеспечивает гораздо более простую модель программирования плюс те же характеристики производительности, что иSocketAsyncEventArgs
. Но во всех проектах, которые я изучал (например, Fraction (F#), SocketAwaitable, SuperSocket и многих других примерах и сообщениях в блогах здесь и там), я не могу найти никого, кто использовал быTcpListener
. Теперь я спрашиваю, почему? - person Kaveh Shahbazian   schedule 03.01.2015