Остановка TcpListener после вызова BeginAcceptTcpClient

Больше расширение вопроса, чем ответ, но это может добавить некоторую перспективу к большим техническим ответам выше. Я опытный программист во многих областях, но я просто программист для веба. Сейчас пытаюсь создать веб-приложение с использованием Zend Framework.

Определенно будет реализован базовый интерфейс аутентификации имени пользователя и пароля для конкретного приложения, но следует понимать, что для растущего числа пользователей мысль о еще одном имени пользователя и пароле является сдерживающим фактором. Хотя это не совсем социальные сети, я знаю, что очень большой процент потенциальных пользователей приложения уже имеют аккаунты в Facebook или Twitter. Приложение на самом деле не хочет или не нуждается в доступе к информации об учетной записи пользователя с этих сайтов, оно просто предлагает удобство, не требующее от пользователя установки новых учетных данных учетной записи, если они этого не хотят. С функциональной точки зрения это может показаться дочерним для OpenID. Но похоже, что ни Facebook, ни Twitter не являются поставщиками OpenID как таковые, хотя они поддерживают аутентификацию OAuth для доступа к данным своих пользователей.

Во всех статьях, которые я читал об этих двух вещах и о том, как они различаются, не было до тех пор, пока я не увидел вышеизложенное замечание Карла Андерсона, что «OAuth может использоваться для аутентификации, которую можно рассматривать как неактивную». разрешение ", что я видел любое явное подтверждение того, что OAuth был достаточно хорош для того, что я хотел сделать.

На самом деле, когда я отправил этот «ответ», не будучи участником в то время, я долго и пристально смотрел внизу этой страницы варианты идентификации себя. Возможность использовать логин OpenID или получить его, если у меня его не было, но ничего о твиттере или фейсбуке, казалось, подсказывала, что OAuth не подходит для этой работы. Но затем я открыл другое окно и искал общий процесс регистрации для stackoverflow - и вот, есть множество вариантов аутентификации сторонних производителей, включая Facebook и Twitter. В конце концов, я решил использовать свой идентификатор Google (который является OpenID) именно по той причине, что я не хотел предоставлять доступ stackoverflow к своему списку друзей и всему остальному, что Facebook любит делиться своими пользователями - но по крайней мере это доказательство того, что OAuth подходит для использования, которое я имел в виду.

Было бы замечательно, если бы кто-то мог либо опубликовать информацию, либо указатели на информацию о поддержке такого рода множественных настроек авторизации из 3-х частей, а также о том, как вы общаетесь с пользователями, которые отменяют авторизацию или теряют доступ к своему стороннему сайту. У меня также создается впечатление, что мое имя пользователя здесь идентифицирует уникальную учетную запись stackoverflow, к которой я мог бы получить доступ с помощью обычной аутентификации, если бы я хотел ее настроить, а также получить доступ к этой же учетной записи через другие сторонние аутентификаторы (например, чтобы меня считали зарегистрированным). в StackOverflow, если я вошел в любой из Google, Facebook или Twitter ...). Поскольку этот сайт занимается этим, у кого-то здесь, возможно, есть довольно хорошее понимание этого вопроса. : -)

Извините, это было так долго, и больше вопрос, чем ответ - но замечание Карла показалось, что это наиболее подходящее место для публикации среди томов потоков на OAuth и OpenID. Если есть лучшее место для этого, которого я не нашел, заранее прошу прощения, я попробовал.

20
задан Anthony D 23 July 2009 в 19:43
поделиться

2 ответа

Я сам столкнулся с этой проблемой и считаю, что ваше текущее решение неполное / неверное. Нет гарантии атомарности между проверкой IsBound и последующим вызовом EndAcceptTcpClient () . Вы по-прежнему можете получить исключение, если слушатель находится между этими двумя операторами Stop () 'd. Вы не сказали, какое исключение вы получаете, но я предполагаю, что это то же самое, что и я, ObjectDisposedException (жалуется, что базовый сокет уже удален).

Вы должны иметь возможность проверьте это, смоделировав планирование потоков:

  • Установите точку останова в строке после проверки IsBound в вашем обратном вызове
  • Заморозьте поток, который попадает в точку останова (окно потоков -> щелкните правой кнопкой мыши, " поскольку вы можете получить различные SocketExceptions . Это просто прикрепление другого обработчика catch к этому блоку try.

    Я признаю, что мне неудобен такой подход, поскольку в принципе перехват может быть ложным срабатыванием с подлинным «плохим» доступом к объекту. Но, с другой стороны, в вызове EndAcceptTcpClient () не так много обращений к объектам, которые в противном случае могли бы вызвать это исключение. Надеюсь.

    Вот мой код. Это ранний / прототип, игнорируйте вызовы консоли.

        private void OnAccept(IAsyncResult iar)
        {
            TcpListener l = (TcpListener) iar.AsyncState;
            TcpClient c;
            try
            {
                c = l.EndAcceptTcpClient(iar);
                // keep listening
                l.BeginAcceptTcpClient(new AsyncCallback(OnAccept), l);
            }
            catch (SocketException ex)
            {
                Console.WriteLine("Error accepting TCP connection: {0}", ex.Message);
    
                // unrecoverable
                _doneEvent.Set();
                return;
            }
            catch (ObjectDisposedException)
            {
                // The listener was Stop()'d, disposing the underlying socket and
                // triggering the completion of the callback. We're already exiting,
                // so just return.
                Console.WriteLine("Listen canceled.");
                return;
            }
    
            // meanwhile...
            SslStream s = new SslStream(c.GetStream());
            Console.WriteLine("Authenticating...");
            s.BeginAuthenticateAsServer(_cert, new AsyncCallback(OnAuthenticate), s);
        }
    
17
ответ дан 30 November 2019 в 00:52
поделиться

Нет, вы ничего не упускаете. Вы можете проверить свойство IsBound объекта Socket. По крайней мере, для TCP-соединений, пока сокет прослушивает это значение, будет установлено значение true, а после вызова close оно будет false. Хотя ваша собственная реализация тоже может работать.

8
ответ дан 30 November 2019 в 00:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: