Difference between revisions of "Twisted"

From JaWiki (Jabber/XMPP wiki)
Jump to: navigation, search
(еще немного описание)
(Пример клиентского приложения)
Line 28: Line 28:
  
 
=== Пример клиентского приложения ===
 
=== Пример клиентского приложения ===
{{Todo|перевести http://yoan.dosimple.ch/blog/2007/01/30/}}
+
Пример простого бота для Jabber-сервера ([http://yoan.dosimple.ch/blog/2007/01/30/ источник])
 +
 
 +
# Эти модули понадобятся.
 +
from twisted.words.protocols.jabber import client, jid
 +
from twisted.xish import domish, xmlstream
 +
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(e.__str__())
 +
      break
 +
 +
# Теперь регистрация callback-а authd.
 +
factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, authd)
 +
 +
# И последнее:
 +
# Создание главного реактора для клиентского TCP соединения
 +
reactor.connectTCP("swissjabber.ch", 5222, factory)
 +
# Запуск реактора
 +
reactor.run()
  
 
== Ссылки ==
 
== Ссылки ==

Revision as of 12:37, 24 May 2007

Twisted
Информация
Адрес: http://twistedmatrix.com/trac/
Язык: Python
Реализация стандартов
Использование
Программы, использующие Twisted

Twisted -- framework для написания сетевых приложений. Предоставляет механизмы для легкой реализации сетевого сервера и клиента. Есть классы облегчающие реализацию своего протокола, а также уже реализована обработка большого числа существующих протоколов, в том числе и XML-потока Jabber-а.

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


Для начинающего Twisted-разработчика

В отличии от многих других библиотек и фреймворков для реализации Jabber-приложений, в twisted-e обработка нескольких клиентских соединений производится не через потоки или процессы, а через конечный автомат (FSM). Это заставляет при написании приложения придерживаться нескольких правил:

  1. Функция не должна долго думать. Так как практически все соединения обрабатываются в одном потоке и в одном цикле, то каждая пауза сказывается на всех. Поэтому "долгие" задачи должны быть выделены в отдельный поток, который в конце работы передаст результат с помощью вызова функции в общем цикле (например с помощью twisted.internet.threads.deferToThread).
  2. Вся работа с внешними и потенциально-тормознутыми данными, это базы данных, сеть и даже работа с файлами, по тем же причинам должна быть разделена на две части (обычно через объект Deferred):
    1. Первая отправляет запрос
    2. Вторая (callback) обрабатывает результат когда он появится.
  3. Вся работа с сетью осуществляется в небезопасном, с точки зрения потоков, режиме. Поэтому для отправки в сеть каких-либо данных из потока необходимо воспользоваться специальными функциями, которые вставят отправку в общий цикл (reactor.callFromThread)

Для Jabber разработчика

Реализация Jabber протокола находится в пакете twisted.words.protocols.jabber.

ToDo: про создание и отправку станз
ToDo: про создание обработчиков

Пример клиентского приложения

Пример простого бота для Jabber-сервера (источник)

# Эти модули понадобятся.
from twisted.words.protocols.jabber import client, jid
from twisted.xish import domish, xmlstream
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(e.__str__())
     break

# Теперь регистрация callback-а authd.
factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, authd)

# И последнее:
# Создание главного реактора для клиентского TCP соединения
reactor.connectTCP("swissjabber.ch", 5222, factory)
# Запуск реактора
reactor.run()

Ссылки

Category:Twisted

См. также