Запишите обратный прокси на апачском сервере перед Вашим приложением, которое реализует Tarpit (Статья Википедии) для наказания ботов. Это просто управляло бы списком IP-адресов, которые соединились за последние несколько секунд. Вы обнаруживаете пакет запросов от единственного IP-адреса и затем экспоненциально задерживаете те запросы перед ответом.
, Конечно, несколько человек могут произойти из того же IP-адреса, если бы они находятся на сетевом соединении NAT'd, но маловероятно, что человек возражал бы против Вашего времени отклика, идя для 2 мс в 4 мс (или даже 400 мс), тогда как боту будет препятствовать увеличивающаяся задержка довольно быстро.
В выбранном вами языке программирования, если идентификатор экспортируется из отдельно скомпилированного модуля, ему требуется имя, под которым он известен во время компоновки. Изменение имени решает проблему перегруженных идентификаторов в языках программирования. (Идентификатор «перегружен», если одно и то же имя используется в более чем одном контексте или имеет более одного значения.)
Некоторые примеры:
В C ++ функция или метод get
могут быть перегружены в нескольких типах.
В Ada или Modula-3 функция get
может появляться в нескольких модулях.
Несколько типов и несколько модулей охватывают обычные контексты.
Типичные стратегии:
] Сопоставьте каждый тип со строкой и используйте объединенный высокоуровневый идентификатор и «строку типа» в качестве имени времени ссылки. Часто встречается в C ++ (особенно просто, поскольку перегрузка разрешена только для функций / методов и только для типов аргументов) и Ada (где вы также можете перегрузить типы результатов).
Если идентификатор используется более чем в одном модуле или пространстве имен, соедините имя модуля с именем идентификатора, например, List_get
вместо List.get
.
В зависимости от того, какие символы допустимы в именах времени компоновки, вы может потребоваться дополнительная обработка; например, может потребоваться использовать подчеркивание в качестве «escape-символа», чтобы можно было отличить
List_my.get
-> List__my_get
от
List.my_get
-> List_my__get
(По общему признанию, этот пример подходит, но как составитель компилятора, Я должен гарантировать, что различных идентификаторов в исходном коде сопоставляются с разными именами времени ссылки . В этом вся причина и цель искажения имен.)
Проще говоря, изменение имен - это процесс, с помощью которого компиляторы изменяют имена идентификаторов в исходном коде, чтобы помочь компоновщику устранить неоднозначность между этими идентификаторами.
В Википедии есть замечательная статья. по этой теме с несколькими замечательными примерами.
Изменение имени - это средство, с помощью которого компиляторы изменяют "скомпилированное" имя объекта, чтобы оно согласованно отличалось от указанного вами.
Это позволяет язык программирования - гибкость, позволяющая давать одно и то же имя нескольким скомпилированным объектам и иметь согласованный способ поиска соответствующего объекта. Например, это позволяет нескольким классам с одним и тем же именем существовать в разных пространствах имен (часто путем добавления пространства имен к имени класса и т. Д.).
Перегрузка операторов и методов на многих языках делает этот шаг дальше - каждый метод заканчивается с "искаженным" именем в скомпилированной библиотеке, чтобы позволить нескольким методам одного типа существовать с одним и тем же именем.
В python изменение имен - это система, при которой переменные класса имеют разные имена внутри и вне класса. Программист "активирует" его, помещая два символа подчеркивания в начале имени переменной.
Например, я могу определить простой класс с некоторыми членами:
>>> class Foo(object):
... def __init__(self):
... self.x = 3
... self._y = 4
... self.__z = 5
...
В практике Python имя переменной, начинающееся с символа подчеркивания, - " внутренний ", а не часть интерфейса класса, поэтому программисты не должны полагаться на него. Тем не менее, это все еще видно:
>>> f = Foo()
>>> f.x
3
>>> f._y
4
Имя переменной, начинающееся с двух знаков подчеркивания, по-прежнему является общедоступным, но оно искажено, и поэтому к нему труднее получить доступ:
>>> f.__z
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__z'
Однако если мы знаем, как работает изменение имени, мы можем получить на это:
>>> f._Foo__z
5
т.е. имя класса добавляется к имени переменной с дополнительным подчеркиванием.
Python не имеет понятия «частный» или «открытый» члены; все публично. Изменение имени - это самый сильный сигнал, который может послать программист, что к переменной нельзя обращаться извне класса.
В Фортране изменение имени необходимо, потому что язык нечувствителен к регистру, а это означает, что Foo, FOO, fOo, foo и т. Д. Будут преобразованы в один и тот же символ, имя которого должно быть нормализовано в каким-то образом. Различные компиляторы реализуют искажение по-разному, и это является источником больших проблем при взаимодействии с C или двоичными объектами, скомпилированными с помощью другого компилятора. Например, GNU g77 / g95 всегда добавляет завершающий знак подчеркивания к имени в нижнем регистре, если имя уже не содержит одного или нескольких подчеркиваний. В этом случае добавляются два символа подчеркивания.
Например, следующая процедура
program test
end program
subroutine foo()
end subroutine
subroutine b_ar()
end subroutine
subroutine b_a_r()
end subroutine
производит следующие искаженные символы:
0000000000400806 g F .text 0000000000000006 b_ar__
0000000000400800 g F .text 0000000000000006 foo_
000000000040080c g F .text 0000000000000006 b_a_r__
Чтобы вызвать код Fortran из C, необходимо вызвать правильно измененное имя подпрограммы (очевидно, сохраняя учитывать возможные различные стратегии искажения, чтобы быть действительно независимыми от компилятора). Чтобы вызвать код C из fortran, интерфейс, написанный на C, должен экспортировать правильно искаженные имена и перенаправить вызов в подпрограмму C. Затем этот интерфейс можно вызвать из Фортрана.