香港云主机最佳企业级服务商!

ADSL拨号VPS包含了中国大陆(联通,移动,电信,)

中国香港,国外拨号VPS。

当前位置:云主机 > python >

电信ADSL拨号VPS
联通ADSL拨号VPS
移动ADSL拨号VPS

使用Python的Twisted框架编写简单的网络客户端


时间:2021-11-09 10:32 作者:admin610456


Protocol
服务器一样,也是通过该类来实现。先看一个简短的例程:

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

在本程序中,只是简单的将获得的数据输出到标准输出中来显示,还有很多其他的事件没有作出任何响应,下面
有一个回应其他事件的例子:

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

本协议连接到服务器,发送了一个问候消息,然后关闭了连接。
connectionMade事件通常被用在建立连接的事件发生时触发。关闭连接的时候会触发connectionLost事件函数

(Simple, single-use clients)简单的单用户客户端
在许多情况下,protocol仅仅是需要连接服务器一次,并且代码仅仅是要获得一个protocol连接的实例。在
这样的情况下,twisted.internet.protocol.ClientCreator提供了一个恰当的API

from twisted.internet import reactorfrom twisted.internet.protocol import Protocol, ClientCreatorclass 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)


ClientFactory(客户工厂)
ClientFactory负责创建Protocol,并且返回相关事件的连接状态。这样就允许它去做像连接发生错误然后
重新连接的事情。这里有一个ClientFactory的简单例子使用Echo协议并且打印当前的连接状态

from twisted.internet.protocol import Protocol, ClientFactoryfrom sys import stdoutclass 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 reactorreactor.connectTCP(host, port, EchoClientFactory())reactor.run()

注意:clientConnectionFailed是在Connection不能被建立的时候调用,clientConnectionLost是在连接关闭的时候被调用,两个是有区别的。


Reconnection(重新连接)
许多时候,客户端连接可能由于网络错误经常被断开。一个重新建立连接的方法是在连接断开的时候调用

connector.connect()方法。

from twisted.internet.protocol import ClientFactoryclass EchoClientFactory(ClientFactory):  def clientConnectionLost(self, connector, reason):    connector.connect()

connector是connection和protocol之间的一个接口被作为第一个参数传递给clientConnectionLost,

factory能调用connector.connect()方法重新进行连接
然而,许多程序在连接失败和连接断开进行重新连接的时候使用ReconnectingClientFactory函数代替这个

函数,并且不断的尝试重新连接。这里有一个Echo Protocol使用ReconnectingClientFactory的例子:

from twisted.internet.protocol import Protocol, ReconnectingClientFactoryfrom sys import stdoutclass 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)


A Higher-Level Example: ircLogBot
上面的所有例子都非常简单,下面是一个比较复杂的例子来自于doc/examples目录

# twisted importsfrom twisted.words.protocols import ircfrom twisted.internet import reactor, protocolfrom twisted.python/' target='_blank'>python import log# system importsimport time, sysclass 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 made  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的。

Persistent Data in the Factory
由于Protocol在每次连接的时候重建,客户端需要以某种方式来记录数据以保证持久化。就好像日志机器人一样他需要知道那个那个频道正在登陆,登陆到什么地方去。

from twisted.internet import protocolfrom twisted.protocols import ircclass 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会获得他本身的一个实例的引用。然后,就能够在factory中存在他的属性。

更多的信息:
本文档讲述的Protocol类是IProtocol的子类,IProtocol方便的被应用在大量的twisted应用程序中。要学习完整的 IProtocol接口,请参考API文档IProtocol.
在本文档一些例子中使用的trasport属性提供了ITCPTransport接口,要学习完整的接口,请参考API文档ITCPTransport
接口类是指定对象有什么方法和属性以及他们的表现形式的一种方法。参考 Components: Interfaces and Adapters文档

(责任编辑:admin)






帮助中心
会员注册
找回密码
新闻中心
快捷通道
域名登录面板
虚机登录面板
云主机登录面板
关于我们
关于我们
联系我们
联系方式

售前咨询:17830004266(重庆移动)

企业QQ:383546523

《中华人民共和国工业和信息化部》 编号:ICP备00012341号

Copyright © 2002 -2018 香港云主机 版权所有
声明:香港云主机品牌标志、品牌吉祥物均已注册商标,版权所有,窃用必究

云官方微信

在线客服

  • 企业QQ: 点击这里给我发消息
  • 技术支持:383546523

  • 公司总台电话:17830004266(重庆移动)
  • 售前咨询热线:17830004266(重庆移动)