“Безопасный дескриптор был закрыт” с SerialPort и потоком в C#

Метод использование Woot для борьбы с этой проблемой изменяет игру - буквально. Когда они представляют чрезвычайно желательный объект для продажи, они заставляют пользователей играть в видеоигру для упорядочивания его.

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

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

<час>

Ваша вся бизнес-модель на основе "первого, прибывают, сначала подаваемые". Вы не можете сделать то, что радиостанции сделали (они больше не делают первую вызывающую сторону победителем, они делают 5-е или 20-й или 13-й вызывающей стороной победитель) - это не соответствует Вашей основной функции.

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

Скажем, Вы реализуете всю эту тактику. Если я решу, что это важно, то я просто заставлю 100 человек работать со мной, мы создадим программное обеспечение, чтобы работать над нашими 100 отдельными компьютерами и поразить Ваш сайт 20 раз в секунду (5 секунд между доступами для каждого ПОЛЬЗОВАТЕЛЯ/COOKIE/УЧЕТНОЙ ЗАПИСИ/IP-АДРЕСА).

у Вас есть два этапа:

  1. первая полоса Наблюдения
  2. Упорядочивание

Вы не можете поместить блокирование капчи № 1 - это собирается потерять настоящих клиентов ("Что? Я должен решить капчу каждый раз, когда я хочу видеть последний woot?!?").

Так мои небольшие часы группы, синхронизированные вместе, таким образом, мы получаем приблизительно 20 проверок в секунду, и кто бы ни видит, изменение сначала предупреждает все другие (автоматически), кто загрузит первую полосу еще раз, перейдет по ссылке порядка и выполнит транзакцию (который может также произойти автоматически, если Вы не реализуете капчу и изменяете ее для каждого wootoff/boc).

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

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

Первый, избавьтесь от простых ботов

, у Вас должен быть адаптивный брандмауэр, который будет наблюдать запросы и если кто-то делает, очевидная глупая вещь - обновляющий несколько раз секунду в том же IP затем используют тактику для замедления их (пакеты отбрасывания, для передачи обратно отказались или 500 ошибок, и т.д.).

Это должно значительно отбросить Ваш трафик и изменить тактику, которую используют пользователи бота.

111-секундный, сделайте сервер ослепительно быстро.

Вы действительно не хотите слышать это..., но...

я думаю, в чем Вы нуждаетесь, полностью настраиваемое решение с самого начала.

Вы не должны смешивать со стеком TCP/IP, но Вы, возможно, должны разработать очень, очень, очень быстро пользовательский сервер, который является целью, созданной, чтобы коррелировать пользовательские соединения и реагировать соответственно на различные нападения.

Apache, lighthttpd, и т.д. является всем великим для того, чтобы быть гибким, но Вы выполняете единственный веб-сайт цели, и действительно необходимо смочь обоим, делают больше, чем текущие серверы способны к выполнению (и в обработке трафика, и в соответственно сражающихся ботах).

Путем обслуживания в основном статической веб-страницы (обновляет каждые 30 секунд или так) на пользовательском сервере необходимо не только смочь обработать 10x количество запросов и трафика (потому что сервер ничего не делает кроме получения запроса и читать страницу из памяти в буфер TCP/IP), но это также предоставит Вам доступ к метрикам, которые могли бы помочь Вам замедлить ботов. Например, путем корреляции IP-адресов можно просто заблокировать больше чем одно соединение в секунду на IP. Люди не могут пойти быстрее, чем это, и даже люди, использующие тот же IP-адрес NATed, будут только нечасто блокироваться. Вы хотели бы сделать, медленный блок - оставляет соединение в покое в течение целой секунды прежде официально завершить сессию. Это может питаться в брандмауэр, чтобы дать долгосрочные блоки особенно вопиющим преступникам.

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

Заключение

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

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

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

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

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

Даже при создании первой полосы капчой для получения до страницы упорядочивания ("Кнопка упорядочивания этого объекта является синим с розовыми блесками, где-нибудь на этой странице") боты будут просто открывать все ссылки на странице и использовать, какой бы ни каждый приезжает назад со страницей упорядочивания. Это не просто никакой способ выиграть это.

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

-Adam

7
задан Daniel A. White 23 August 2009 в 16:53
поделиться

2 ответа

Я подозреваю, что это потому, что вы используете Thread.Abort для завершения потока, что обычно не одобряется. Поведение потока при прерывании непредсказуемо. Из-за этого, поскольку последовательный порт является оболочкой над собственным кодом, существуют собственные ресурсы, представленные SafeHandle в .NET, которые неожиданно удаляются, и вы получаете исключение.

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

  • вы запускаете свой поток
  • вы открываете последовательный порт (который выделяет собственные ресурсы и использует SafeHandle (s) для удержания этих ресурсов)
  • вы начинаете чтение из последовательного порта
  • , затем в какой-то момент (неожиданно для вашего потока) вы вызываете Thread. Прервать его
  • скорее всего, в этот момент код в вашем потоке пытается получить доступ к последовательному порту (для чтения данных)
  • поток завершается, и дескриптор последовательного порта уничтожается неявно
  • вы получаете исключение выброшенный из кода внутри функции ReadLine () последовательного порта, потому что дескриптор, который у него был, больше не действителен

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

Правильный способ закрытия потока может быть реализован с помощью ManualResetEvent следующим образом:

protected ManualResetEvent threadStop = new ManualResetEvent(false);

protected void ReadData()
{
     SerialPort serialPort = null;
     try
     {
         serialPort = SetupSerialPort(_serialPortSettings);
         serialPort.Open();

         string data;
         while (serialPort.IsOpen)
         {
             try
             {

                 data = serialPort.ReadLine();
                 if (data.Length > 0)
                     ReceivedData(serialPort, new ReceivedDataEventArgs(data));

             }
             catch (TimeoutException)
             {
                 //  No action
             }

             // WaitOne(0) tests whether the event was set and returns TRUE
             //   if it was set and FALSE otherwise.
             // The 0 tells the manual reset event to only check if it was set
             //   and return immediately, otherwise if the number is greater than
             //   0 it will wait for that many milliseconds for the event to be set
             //   and only then return - effectively blocking your thread for that
             //   period of time
             if (threadStop.WaitOne(0))
                 break;
         }
     }
     catch (Exception exc)
     {
         // you can do something here in case of an exception
         // but a ThreadAbortedException should't be thrown any more if you
         // stop using Thread.Abort and rely on the ManualResetEvent instead
     }
     finally
     {
         if (serialPort != null)
             serialPort.Close();
     }
}

protected void Stop()
{
    // Set the manual reset event to a "signaled" state --> will cause the
    //   WaitOne function to return TRUE
    threadStop.Set();
} 

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

10
ответ дан 7 December 2019 в 01:24
поделиться

Попал в похожую ситуацию, когда я попытался создать соединения последовательного порта локальным методом. Идея состояла в том, чтобы создать до четырех объектов serialPort (для каждого последовательного порта). Как только один из портов вернется с хорошими данными, я буду знать, к какому порту подключено мое устройство. Я бы отбрасывал все свои "пробные" объекты и создавал новое соединение с определенным com-портом.

Каждый раз с помощью этого метода я бы создавал/отбрасывал свои объекты serialPort. Упс. Так получилось, что если бы GC не запустился к тому времени, как я снова вызвал метод, он попытался бы создать второе последовательное соединение, заменяющее первое соединение, и они бы столкнулись. Это спровоцировало бы эту ошибку. Решение: сделать все объекты подключения к последовательному порту глобальными для класса. Ugly Hack: Да, но он работает

.
0
ответ дан 7 December 2019 в 01:24
поделиться
Другие вопросы по тегам:

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