`
guangboo
  • 浏览: 34602 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Twisted教程-客户端

阅读更多

原文:http://www.klipdas.com/blog/?p=twisted-clients

客户端

2.2.1 概述.

Twisted框架设计的很灵活,可以编写功能强大的客户端。灵活的代价在于编写客户端方法的多一些层次,文档涵盖了使用TCP,SSL和Unix sockets,UDP来创建客户端,它们分别都有介绍(92页)。

基本上,实际实现协议的解析和处理的是在Protocol类中。该类通常继承至twisted.internet.protocol.Protocol,大多数协议处理程序要么继承至该类,要么是其子类。当你连接到服务器时协议类就会实例化一个实体,在你离开的时候,被释放。就是说持久的配置不会驻留在Protocol中。

持久配置被保存在Factory类中,它通常继承至twisted.internet.protocol.ClientFactory。默认的工厂类只实例化Protocol,并赋值给它的factory属性,这就允许Protocol访问,有可能修改持久化配置。

2.2.2 协议

如上所述,协议、辅助类和函数是大部分代码。Twisted协议以异步形式处理数据,就是说协议从不等待事件,而是在收到事件时回复。 示例:

from twisted.internet.protocol import Protocol
from sys import stdout
class Echo(Protocol):
  def dataReceived(self, data):
  stdout.write(data)

这是一个最简单的协议,只是简单的将接收到的数据写入标准输出中去,还有很多的事件它没有响应。下面时候Protocol响应其他事情的示例:

from twisted.internet.protocol import Protocol
class WelcomeMessage(Protocol):
  def connectionMade(self):
    self.transport.write("Hello server, I am the client!\r\n")
    self.transport.loseConnection()

该协议连接到服务器,发送一条欢迎消息,然后终止连接。

connectionMade事件通常发生在Protocol对象设置的地方,同时初始化问候语(就像上面的WelcomeMessage协议)。特定的Protocol对象会在connectionLost事件中被清除。

2.2.3 简易单用户客户端

很多情况下,协议只需要连接服务器一次,程序只想获取一个协议连接的实例。这些情况下,twisted.internet.protocol.ClientCreator提供了必要的API。

from twisted.internet import reactor
from twisted.internet.protocol import Protocol, ClientCreator

class Greeter(Protocol):
  def sendMessage(self, msg):
  	self.transport.write("MESSAGE %s\n" % msg)
    
  def gotProtocol(p):
  	p.sendMessage("Hello")
  	reactor.callLater(1, p.sendMessage, "This is sent in a second")
  	reactor.callLater(2, p.transport.loseConnection)
    
c = ClientCreator(reactor, Greeter)
c.connectTCP("localhost", 1234).addCallback(gotProtocol)

2.2.4 ClientFactory

我们使用reactor.connect*和ClientFactory,该ClientFactory负责创建Protocol,并接收与连接状态相关的事件,它可以做一些工作,如在连接错误事件中进行重新连接。下面是一个简单ClientFactory的示例,它使用Echo协议(见上述)并打印出连接状态。

from twisted.internet.protocol import Protocol, ClientFactory
from sys import stdout

class Echo(Protocol):
    def dataReceived(self, data):
    	stdout.write(data)

class EchoClientFactory(ClientFactory):
    def startedConnecting(self, connector):
    	print 'Started to connect.'
        
    def buildProtocol(self, addr):
		print 'Connected.'
		return Echo()
        
    def clientConnectionLost(self, connector, reason):
		print 'Lost connection, Reason:', reason
        
	def clientConnectionFailed(self, connector, reason):
		print 'Connection failed. Reason:', reason

为使EchoClientFactory连接服务器,添加如下代码:

from twisted.internet import reactor

reactor.connectTCP(host, port, EchoClientFactory())
reactor.run()

注意:clientConnectionFailed在不能建立连接时被调用,clientConnectionLost在创建连接后被释放时调用。

重新连接

很多时候,由于网络错误,客户端连接就会丢失意义。有一种方法,在连接中断时,disconnection会调用connector.connect()来重新进行连接:

from twisted.internet.protocol import ClientFactory

class EchoClientFactory(ClientFactory):
	def clientConnectionLost(self, connector, reason):
		connector.connect()

作为第一个参数传递的connector是connection和protocol的接口,当连接失败,factory收到clientConnectionLost事件时,factory可以调用connector.connect()来从头开始建立连接。

然而,大部分需要这个功能的程序应该是实现ReconnectingClientFactory,它在连接中断或失败时尝试重新连接,不断的延时并不断尝试重新连接。

下面是实现了ReconnectingClientFactory的Echo协议:

from twisted.internet.protocol import Protocol, ReconnectingClientFactory
from sys import stdout

class Echo(Protocol):
	def dataReceived(self, data):
		stdout.write(data)

class EchoClientFactory(ReconnectingClientFactory):
	def startedConnecting(self, connector):
		print 'Started to connect.'

	def buildProtocol(self, addr):
		print 'Connected.'
		print 'Resetting reconnection delay'
		self.resetDelay()
		return Echo()

	def clientConnectionLost(self, connector, reason):
		print 'Lost connection. Reason:', reason
		ReconnectingClientFactory.clientConnectionLost(self, connector, reason)

	def clientConnectionFailed(self, connector, reason):
		print 'Connection failed. Reason:', reason
		ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)

2.2.5 高级示例: ircLogBot

ircLogBot简介

到现在的客户端还相当简单,更复杂的示例在Twisted文档的doc/examples目录下面。

from twisted.words.protocols import irc
from twisted.internet import reactor, protocol
from twisted.python import log

import time, sys

class MessageLogger:
    """
    An independent logger class (because separation of application
    and protocol logic is a good thing).
    """
    def __init__(self, file):
        self.file = file

    def log(self, message):
        """Write a message to the file."""
        timestamp = time.strftime("[%H:%M:%S]", time.localtime(time.time()))
        self.file.write('%s %s\n' % (timestamp, message))
        self.file.flush()

    def close(self):
        self.file.close();

class LogBot(irc.IRCClient):
    """A logging IRC bot."""
    nickname = "twistedbot"

    def connectionMade(self):
        irc.IRCClient.connectionMade(self)
        self.logger = MessageLogger(open(self.factory.filename, "a"))
        self.logger.log("[connected at %s]" %time.asctime(time.localtime(time.time())))

    def connectionLost(self, reason):
        irc.IRCClient.connectionLost(self, reason)
        self.logger.log("[disconnected at %s]" % time.asctime(time.localtime(time.time())))
        self.logger.close()

    #callbacks for events
    def signedOn(self):
        """Called when bot has succesfully signed on to server."""
        self.join(self.factory.channel)

    def joined(self, channel):
        """This will get called when the bot joins the channel."""
        self.logger.log("[I have joined %s]" % channel)

    def privmsg(self, user, channel, msg):
        """This will get called when the bot receives a message."""
        user = user.split('!', 1)[0]
        self.logger.log("<%s> %s" % (user, msg))

        #Check to see if they're sending me a private message
        if channel == self.nickname:
            msg = "It isn't nice to whisper! Play nice with the group."
            self.msg(user, msg)
            return
        #Otherwise check to see if it is a message directed at me
        if msg.startswith(self.nickname + ":"):
            msg = "%s: I am a log bot" % user
            self.msg(channel, msg)
            self.logger.log("<%s> %s" % (self.nickname, msg))

    def action(self, user, channel, msg):
        """This will get called when the bot sees someone do an action."""
        user = user.split('!', 1)[0]
        self.logger.log("* %s %s" % (user, msg))

    #irc callbacks
    def irc_NICK(self, prefix, params):
        """Called when an IRC user changes their nickname."""
        old_nick = prefix.split('!')[0]
        new_nick = params[0]
        self.logger.log("%s is now known as %s" % (old_nick, new_nick))


class LogBotFactory(protocol.ClientFactory):
    """A factory for LogBots

    A new protocol instance will be created each time we connect to the server.
    """
    #the class of the protocol to build when new connection is mede
    protocol = LogBot

    def __init__(self, channel, filename):
        self.channel = channel
        self.filename = filename

    def clientConnectionLost(self, connector, reason):
        """If we get disconnected, reconnect to server."""
        connector.connect()

    def clientConnectionFailed(self, connector, reason):
        print "connection failed:", reason
        reactor.stop()

if __name__ == '__main__':
    #initialize logging
    log.startLogging(sys.stdout)

    #create factory protocol and application
    f = LogBotFactory(sys.argv[1], sys.argv[2])

    #connect factory to this host and port
    reactor.connectTCP("irc.freenode.net", 6667, f)

    #run bot
    reactor.run()

ircLogBot.py连接IRC服务器,调入一个频道并将所以流量记录到文件中,它表明了连接中断时重新连接的连接层逻辑,以及Factory中的持久数据。

Factory中的持久数据

由于Protocol实例在每次连接时都会重新创建,客户端需要一些方法来跟踪应该被持久化的数据。在这个logging bot案例中,它需要知道哪个频道被记录及记录在哪里。

from twisted.internet import protocol
from twisted.protocols import irc

class LogBot(irc.IRCClient):
	def connectionMade(self):
		irc.IRCClient.connectionMade(self)
		self.logger = MessageLogger(open(self.factory.filename, "a"))
		self.logger.log("[connected at %s]" %time.asctime(time.localtime(time.time())))
	def signedOn(self):
		self.join(self.factory.channel)
        
class LogBotFactory(protocol.ClientFactory):
	protocol = LogBot
	def __init__(self, channel, filename):
		self.channel = channel
		self.filename = filename 

当protocol被创建,它就会得到factory的引用赋值给self.factory,它可以通过自身的逻辑对factory的属性进行访问。在LogBot案例中,它打开文件,并连接factory中的通道存储。

2.2.6 延伸

本书中所使用的Protocol类是实现了IProtocol接口的基本类,该接口在大多少Twisted应用都广泛应用。要了解完整的IProtocol接口,请参阅API文档。

本书中在一些示例中使用的transport属性提供了ITCPTransport接口,要了解有关该接口的详细情况,参阅ITCPTransport的API文档。

接口是用于指定一个类所拥有的或如何使用的方法和属性的。参阅Components:Interfaces和Adapters(文档148页)。

你不知道的淘宝66种生活

0
0
分享到:
评论

相关推荐

    twisted系列教程-中文

    Twisted系列教程中文简介 Twisted是一个基于Python的异步网络编程库,提供了一个灵活的架构来处理异步I/O操作。该教程将从基础开始,逐步深入Twisted的世界,帮助读者了解异步编程的思想和Twisted的使用方法。 ...

    Python-txRedis基于Twisted的Redis客户端

    Python-txRedis是针对Twisted框架的一个高效、异步的Redis客户端库,它允许你在Twisted事件循环中无缝地操作Redis服务器。这个库是为了解决在非阻塞环境中进行数据库交互的需求,使得你的Python应用在处理大量并发...

    中文Twisted入门教程

    ### Twisted入门教程知识点梳理 #### 一、Twisted理论基础 - **异步编程模型简介**:异步编程是一种编程范式,其中程序的控制流不会被阻塞等待某个操作完成,而是允许其他任务继续执行。这在处理I/O密集型任务(如...

    Twisted系列教程 的中文翻译

    本系列教程是对Twisted框架的详细介绍,从基础理论到实际应用,逐步引导读者入门并深入理解Twisted的各种用法。 在第一部分,教程首先介绍了Twisted理论基础,强调了异步编程的重要性以及reactor模式。异步编程模型...

    twisted 异步教程 中文版

    本教程深入介绍了Twisted的理论基础、异步编程模式与Reactor的初探、Twisted支持的客户端与服务器的开发以及Deferred对象的使用。Deferred是Twisted框架中用于处理异步操作完成后的回调函数的对象,它能够帮助开发者...

    twisted入门教程源码

    本教程将深入探讨 Twisted 的基础知识和主要组件。 ### 1. Twisted 的核心概念 - **事件驱动编程**: Twisted 使用非阻塞I/O模型,基于事件循环,当数据就绪时触发回调函数,而非等待I/O操作完成。这使得程序在等待...

    Twisted系列教程.pdf

    ### Twisted系列教程知识点概述 #### 第一部分:Twisted理论基础 - **前言**:这一部分主要介绍了Twisted框架的背景以及对于那些寻求快速入门的读者来说,Twisted可能并非是一个简单易学的选择。作者指出,对于希望...

    twisted例子

    2. **TCP服务**:可能会有一个简单的TCP服务器示例,展示如何使用Twisted来监听和处理客户端的TCP连接。这将涉及`twisted.internet.protocol`和`twisted.internet.endpoints`模块。 3. **UDP通信**:除了TCP,...

    twisted_book

    Twisted 是一个用 Python 编写的事件驱动网络引擎,适用于服务器端和客户端应用程序。它支持多种协议,包括但不限于 TCP、UDP、SSL/TLS、HTTP 和 IRC。Twisted 的设计理念强调了模块化和可扩展性,使得开发人员能够...

    Twisted与异步编程入门

    在本文档的开头,作者指出对于那些希望快速了解Twisted的人来说,本教程可能并不是最佳选择,因为真正理解和掌握Twisted及异步编程需要一定的时间和基础。 #### Twisted理论基础 在正式进入Twisted之前,文档首先...

    python twisted 网络编程教程 有代码示例

    ### Python Twisted 网络编程教程:深入解析与代码示例 #### 一、引言及 Twisted 概览 ##### 1.1 Twisted 的愿景 Twisted 是一个用 Python 编写的事件驱动网络引擎,其核心设计旨在简化异步编程。Twisted 的愿景是...

    The Twisted Documentation 电子版 pdf

    - **第2章 教程**:提供编写服务器与客户端的具体示例,并逐步深入到高级应用场景。 **重要知识点解析:** 1. **扭曲框架的愿景**:构建一个强大且灵活的异步网络框架,支持多种网络协议和服务。 2. **扭曲框架的...

    python2.5 twisted

    “python2.5andtwisted”这个文件可能是一个包含教程或示例代码的文档,展示了如何在Python 2.5环境下安装和使用Twisted框架。学习这个文档将有助于理解如何在旧版本的Python环境中配置和运行Twisted项目。 在实际...

    twisted introduction

    标签中的“文档”则表明给定的文件是一份文档资料,它可能是Twisted框架的官方入门指南、教程或其他形式的文档。 部分内容描述了文档的结构和内容,开始于对异步编程和Twisted框架的简单介绍。文档提到,快速入门...

    twisted资料twisted资料

    这个压缩包包含的文件名为"twistedTUTXX - Woodpecker Wiki for CPUG.mht",其中XX可能是01到11的数字,这些文件很可能是Woodpecker Wiki为计算机用户组(CPUG)编写的关于Twisted框架的教学教程。 Twisted的核心是它...

Global site tag (gtag.js) - Google Analytics