Difference between revisions of "Twisted"
(→Для начинающего Twisted-разработчика: у меня проблемы с ясностью изложения. Это вторая попытка :)) |
m (исправил мелкие огрехи; добавил про поддерживаемые протоколы) |
||
(5 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{Library | {{Library | ||
| name=Twisted | | name=Twisted | ||
− | | url=http://twistedmatrix.com/ | + | <!-- Общая информация --> |
− | | language= | + | | url=[http://twistedmatrix.com/ twistedmatrix.com] |
− | }} | + | | language={{Lang|l|Python}} |
+ | | xmlparser=внутренний (twisted.words.xish) | ||
+ | <!-- Реализация стандартов --> | ||
+ | | roster=нет | ||
+ | <!-- | filetransfer=пересылка файлов --> | ||
+ | | dataforms=нет | ||
+ | | disco=нет | ||
+ | | adhoc=нет | ||
+ | | zip=нет | ||
+ | | pubsub=нет | ||
+ | | pep=нет | ||
+ | | jingle=нет | ||
+ | | jid=да | ||
+ | | sasl=да | ||
+ | | component=да | ||
+ | }} | ||
− | '''Twisted''' | + | '''Twisted''' — фрэймворк для написания сетевых приложений на [[Python]]. |
− | Предоставляет механизмы для легкой реализации сетевого сервера и клиента. | + | Предоставляет механизмы для легкой реализации сетевого сервера и клиента. |
− | Есть классы облегчающие реализацию своего протокола, а также уже реализована обработка большого числа существующих протоколов, в том числе и XML-потока [[Jabber]]-а. | + | Есть классы облегчающие реализацию своего протокола, а также уже реализована обработка большого числа существующих протоколов, в том числе и XML-потока [[Jabber]]-а. |
− | Но работа Twisted не ограничивается только сетью. | + | Но работа Twisted не ограничивается только сетью. |
Этот фреймворк облегчает создание расширяемых с помощью плагинов программ, конструирование многосервисных программ, создание единой авторизации пользователей между сервисами и многое другое. | Этот фреймворк облегчает создание расширяемых с помощью плагинов программ, конструирование многосервисных программ, создание единой авторизации пользователей между сервисами и многое другое. | ||
+ | Работа с [[XMPP]] реализована в модуле <code>twisted.words</code>, который, кроме того, поддерживает {{proto|lib|IRC}}, {{proto|lib|MSN}} (MSNP8, полуэкспериментальная поддержка) и {{proto|lib|OSCAR}}. | ||
== Для начинающего Twisted-разработчика == | == Для начинающего Twisted-разработчика == | ||
− | В | + | В отличие от многих других [[библиотека|библиотек]] и фреймворков для реализации Jabber-приложений, в Twisted обработка нескольких клиентских соединений производится не через потоки или процессы, а через {{w|конечный автомат}}. Это означает, что всех клиентов обслуживает, грубо говоря, ''один поток и один цикл'', а вся ответственность за «параллелизацию» работы c клиентами ложится на плечи программиста, а не ОС. Такой подход признан более эффективным, но и более сложным в исполнении. |
− | К счастью, вся сложная часть уже реализована в | + | К счастью, вся сложная часть уже реализована в Twisted, а программисту остается только создавать свои обработчики событий и придерживаться нескольких правил: |
− | # Функция не должна долго думать. Так все соединения обрабатываются в одном потоке и в одном цикле, то каждая пауза сказывается на всех. Поэтому | + | # Функция не должна долго думать. Так как все соединения обрабатываются в одном потоке и в одном цикле, то каждая пауза сказывается на всех. Поэтому «долгие» задачи (большие вычисления и т. п.) должны быть выделены в отдельный поток, который в конце работы вернет результат с помощью вызова функции в общем цикле (создание потока и возврат результата можно облегчить с помощью <code>twisted.internet.threads.deferToThread</code>). |
− | # Вся работа с внешними и потенциально-тормознутыми данными, а это базы данных, сеть и даже работа с файлами, по тем же причинам должна быть разделена на две части (обычно через объект Deferred): первая отправляет запрос, вторая (callback) обрабатывает результат когда он появится. Для такой работы с большой частью тормознутых объектов уже подготовлены нужные классы. | + | # Вся работа с внешними и потенциально-тормознутыми данными, а это базы данных, сеть и даже работа с файлами, по тем же причинам должна быть разделена на две части (обычно через объект Deferred): первая отправляет запрос, вторая (callback) обрабатывает результат, когда он появится. Для такой работы с большой частью тормознутых объектов уже подготовлены нужные классы. |
− | # Вся работа с сетью осуществляется в небезопасном, с точки зрения потоков, режиме. Поэтому для отправки в сеть каких-либо данных из потока (если вы все же решили выделить отдельный) необходимо воспользоваться специальными функциями, которые вставят отправку в общий цикл (reactor.callFromThread). То же | + | # Вся работа с сетью осуществляется в небезопасном, с точки зрения потоков, режиме. Поэтому для отправки в сеть каких-либо данных из потока (если вы все же решили выделить отдельный) необходимо воспользоваться специальными функциями, которые вставят отправку в общий цикл (<code>reactor.callFromThread</code>). То же касается и других вещей, которые в многопоточной программе требовали блокировок. |
− | == Для Jabber разработчика == | + | == Для Jabber-разработчика == |
− | Реализация Jabber протокола находится в пакете twisted.words.protocols.jabber. | + | Реализация Jabber протокола находится в пакете <code>twisted.words.protocols.jabber</code>. |
− | {{Todo|про создание и отправку | + | {{Todo|про создание и отправку стансов}} |
{{Todo|про создание обработчиков}} | {{Todo|про создание обработчиков}} | ||
− | |||
=== Пример клиентского приложения === | === Пример клиентского приложения === | ||
Пример простого бота для Jabber-сервера ([http://yoan.dosimple.ch/blog/2007/01/30/ источник], адаптирован для работы с Twisted 2.5.0) | Пример простого бота для Jabber-сервера ([http://yoan.dosimple.ch/blog/2007/01/30/ источник], адаптирован для работы с Twisted 2.5.0) | ||
− | |||
# Эти модули понадобятся. | # Эти модули понадобятся. | ||
Line 39: | Line 53: | ||
me = jid.JID("greutly@swissjabber.ch/TwistedWords") | me = jid.JID("greutly@swissjabber.ch/TwistedWords") | ||
− | # Так как бот -- это клиентское приложение, то и factory (см [http://twistedmatrix.com/projects/core/documentation/howto/glossary.html#Factory глоссарий]) | + | # Так как бот -- это клиентское приложение, то и factory (см. [http://twistedmatrix.com/projects/core/documentation/howto/glossary.html#Factory глоссарий]) |
− | # тоже будет клиентским. | + | # тоже будет клиентским. Модуль twisted.words.protocols.jabber.client |
# предоставляет класс для создания factory Jabber-клиентов. | # предоставляет класс для создания factory Jabber-клиентов. | ||
factory = client.basicClientFactory(me, "password") | factory = client.basicClientFactory(me, "password") | ||
Line 66: | Line 80: | ||
# пришло. | # пришло. | ||
def gotMessage(message): | def gotMessage(message): | ||
− | # sorry for the | + | # sorry for the str(), makes unicode happy |
print u"from: %s" % message["from"] | print u"from: %s" % message["from"] | ||
for e in message.elements(): | for e in message.elements(): | ||
if e.name == "body": | if e.name == "body": | ||
− | print unicode( | + | print unicode(str(e)) |
break | break | ||
Line 83: | Line 97: | ||
== Ссылки == | == Ссылки == | ||
− | |||
− | |||
− | |||
* [http://www.opennet.ru/base/dev/server_way.txt.html Подходы к организации серверного приложения] | * [http://www.opennet.ru/base/dev/server_way.txt.html Подходы к организации серверного приложения] | ||
* [http://twistedmatrix.com/documents/current/api/ Twisted API] | * [http://twistedmatrix.com/documents/current/api/ Twisted API] | ||
− | * [http://twistedmatrix.com/projects/core/documentation/howto/index.html | + | * [http://twistedmatrix.com/projects/core/documentation/howto/index.html Документация] |
* [http://ru.pywiki.com/index.php/Twisted Twisted на русскоязычной Python wiki] | * [http://ru.pywiki.com/index.php/Twisted Twisted на русскоязычной Python wiki] | ||
− | * [http://twistedmatrix.com/projects/core/documentation/howto/tutorial/index.html | + | * [http://twistedmatrix.com/projects/core/documentation/howto/tutorial/index.html Пример реализации] протокола {{w|Finger}} с помощью Twisted |
Latest revision as of 21:10, 11 July 2010
Twisted | |
---|---|
Информация | |
Адрес: | twistedmatrix.com |
Язык: | Python |
XML-парсер: | внутренний (twisted.words.xish) |
Реализация стандартов | |
Анализ JID-а: | да |
SASL-авторизация: | да |
Регистрация компонента: | да |
Ростер: | нет |
Data Forms: | нет |
Service Discovery: | нет |
Ad-Hoc команды: | нет |
Сжатие XML потока: | нет |
PubSub: | нет |
PEP: | нет |
Jingle: | нет |
Использование | |
Программы, использующие Twisted |
Twisted — фрэймворк для написания сетевых приложений на Python. Предоставляет механизмы для легкой реализации сетевого сервера и клиента. Есть классы облегчающие реализацию своего протокола, а также уже реализована обработка большого числа существующих протоколов, в том числе и XML-потока Jabber-а.
Но работа Twisted не ограничивается только сетью. Этот фреймворк облегчает создание расширяемых с помощью плагинов программ, конструирование многосервисных программ, создание единой авторизации пользователей между сервисами и многое другое.
Работа с XMPP реализована в модуле twisted.words
, который, кроме того, поддерживает IRC, MSN (MSNP8, полуэкспериментальная поддержка) и OSCAR.
Contents
Для начинающего Twisted-разработчика[edit]
В отличие от многих других библиотек и фреймворков для реализации Jabber-приложений, в Twisted обработка нескольких клиентских соединений производится не через потоки или процессы, а через конечный автомат. Это означает, что всех клиентов обслуживает, грубо говоря, один поток и один цикл, а вся ответственность за «параллелизацию» работы c клиентами ложится на плечи программиста, а не ОС. Такой подход признан более эффективным, но и более сложным в исполнении.
К счастью, вся сложная часть уже реализована в Twisted, а программисту остается только создавать свои обработчики событий и придерживаться нескольких правил:
- Функция не должна долго думать. Так как все соединения обрабатываются в одном потоке и в одном цикле, то каждая пауза сказывается на всех. Поэтому «долгие» задачи (большие вычисления и т. п.) должны быть выделены в отдельный поток, который в конце работы вернет результат с помощью вызова функции в общем цикле (создание потока и возврат результата можно облегчить с помощью
twisted.internet.threads.deferToThread
). - Вся работа с внешними и потенциально-тормознутыми данными, а это базы данных, сеть и даже работа с файлами, по тем же причинам должна быть разделена на две части (обычно через объект Deferred): первая отправляет запрос, вторая (callback) обрабатывает результат, когда он появится. Для такой работы с большой частью тормознутых объектов уже подготовлены нужные классы.
- Вся работа с сетью осуществляется в небезопасном, с точки зрения потоков, режиме. Поэтому для отправки в сеть каких-либо данных из потока (если вы все же решили выделить отдельный) необходимо воспользоваться специальными функциями, которые вставят отправку в общий цикл (
reactor.callFromThread
). То же касается и других вещей, которые в многопоточной программе требовали блокировок.
Для Jabber-разработчика[edit]
Реализация Jabber протокола находится в пакете twisted.words.protocols.jabber
.
Пример клиентского приложения[edit]
Пример простого бота для Jabber-сервера (источник, адаптирован для работы с Twisted 2.5.0)
# Эти модули понадобятся. from twisted.words.protocols.jabber import client, jid, xmlstream from twisted.words.xish import domish from twisted.internet import reactor # Для JID-а используем специальный Twisted-класс me = jid.JID("greutly@swissjabber.ch/TwistedWords") # Так как бот -- это клиентское приложение, то и factory (см. глоссарий) # тоже будет клиентским. Модуль twisted.words.protocols.jabber.client # предоставляет класс для создания factory Jabber-клиентов. factory = client.basicClientFactory(me, "password") # FSM полностью строится на callback-ах. Ждать нельзя. Поэтому писать # что-то вроде "открыть сокет, подождать ответ, послать логин/пароль, # подождать и т.д." тоже нельзя. Для того, чтобы выполнить какие-то # определенные действия после авторизации, необходимо создать callback: def authd(xmlstream): # создание XML элемента presence. presence = domish.Element(('jabber:client', 'presence')) presence.addElement('status').addContent('Online') # отправка в xmlstream. Обратите внимание, что это безопасная отправка, # так как эта функция вызывалась из главного цикла и в данный момент мы # единственные, кто сейчас работает с потоком. Остальные, если есть, ждут. xmlstream.send(presence) # Установка обработчика на входящие XML-элементы message. Первый # параметр -- это XPath xmlstream.addObserver('/message', gotMessage) # сам обработчик. параметр message -- XML-элемент # основная функция обработчика -- печатать то, что # пришло. def gotMessage(message): # sorry for the str(), makes unicode happy print u"from: %s" % message["from"] for e in message.elements(): if e.name == "body": print unicode(str(e)) break # Теперь регистрация callback-а authd. factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, authd) # И последнее: # Создание главного реактора для клиентского TCP соединения reactor.connectTCP("swissjabber.ch", 5222, factory) # Запуск реактора reactor.run()
Ссылки[edit]
- Подходы к организации серверного приложения
- Twisted API
- Документация
- Twisted на русскоязычной Python wiki
- Пример реализации протокола Finger с помощью Twisted