Сокет-сервер перестает принимать соединения через некоторое время - PullRequest
3 голосов
/ 16 мая 2010

У нас есть сервер асинхронных сокетов, написанный на C #. (работает на Windows Web Server 2008)

Работает без сбоев до тех пор, пока не прекратит принимать новые соединения по неизвестной причине.

У нас в среднем около 200 одновременных подключений, однако мы сохраняем количество созданных и потерянных подключений. Эти цифры могут достигать 10000 или только 1000, прежде чем он просто остановится! Он может работать до 8 часов, иногда до остановки, или может работать около получаса, в то время как он работает около часа, прежде чем у нас другое приложение автоматически восстановит его, когда не удается подключиться (не совсем идеал).

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

Мы можем понять это. У кого-нибудь есть идеи, что может происходить?

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

Ответы [ 3 ]

3 голосов
/ 16 мая 2010

Кто инициирует активное закрытие, клиент или сервер? Если это сервер, то вы можете накапливать сокеты в состоянии TIME_WAIT на сервере, и это может помешать вам принимать новые подключения. Это более вероятно, если клиентские соединения могут быть недолговечными, и вы проходите через периоды, когда происходит много недолговечных клиентских соединений.

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

1 голос
/ 24 апреля 2017

Я почти уверен, что OP столкнулся с фатальной комбинацией проблем, с которыми мы столкнулись:

  1. Звонок на SslStream.AuthenticateAsServer после принятия соединения был заблокирован навсегда, скорее всего из-за сбоя клиента после подключения, например, проблема полуоткрытое соединение . Этот вызов вызывает синхронное чтение под крышками, следовательно, возможна блокировка.
  2. .NET вызывал обратный вызов, переданный Socket.BeginAccept синхронно в том же потоке, который инициировал принятие, то есть в потоке прослушивания вашего сервера. Это совершенно неожиданно, но они документируют это, см. Замечания по BeginAccept .

Комбинируя эти проблемы, вы получаете серию событий:

  1. Ваш основной поток прослушивания вызывает Socket.BeginAccept.
  2. .NET решает синхронно вызвать ваш обратный вызов принятия в потоке прослушивания.
  3. Ваш код подтверждения вызывает SslStream.AuthenticateAsServer (или любой другой блокирующий вызов) и ожидает ответа, который никогда не приходит ... бинго, ваша цепочка прослушивания заблокирована навсегда!

Мы исправили это, выполнив следующее:

  • Установите ReceiveTimeout на разъем, который вы получите после принятия соединения. Это предотвращает блокировку SslStream.AuthenticateAsServer или любое другое чтение синхронизации навсегда.
  • Проверьте, завершен ли обратный вызов принятия синхронно, и если это так, разверните и вручную создайте другой поток, чтобы запустить оставшуюся логику принятия, чтобы прослушивающий поток никогда не был связан с какой-либо обработкой. То есть передать обратный вызов BeginAccept, который делает что-то вроде этого:

    private void AcceptCallbackWithSyncCheck(IAsyncResult asyncResult)
    {
        if (asyncResult.CompletedSynchronously)
        {
            // Force the accept logic to run async, to keep our listening
            // thread free.
            Action accept = () => this.ActualAcceptCallback(asyncResult);
    
            accept.BeginInvoke(accept.EndInvoke, null);
        }
        else
        {
            this.ActualAcceptCallback(asyncResult);
        }
    }
    

Для любопытных мы поняли это, попав в службу множеством одновременных вызовов (используя симулятор клиента), и когда проблема возникла, мы подключились к процессу службы с помощью инструмента удаленной отладки Visual Studio. Это позволило нам сразу увидеть, что поток прослушивания блокируется и где. Однако это произошло только после того, как мы провели пару недель, стуча головой о стену, поэтому я надеюсь, что это поможет бедным душам, которые столкнутся с этим в будущем ...

1 голос
/ 16 мая 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...