日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

使用Python的Twisted框架編寫簡單的網絡客戶端

系統 1686 0

Protocol
? 和服務器一樣,也是通過該類來實現。先看一個簡短的例程:

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

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


          

在本程序中,只是簡單的將獲得的數據輸出到標準輸出中來顯示,還有很多其他的事件沒有作出任何響應,下面
有一個回應其他事件的例子:

            
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事件通常被用在建立連接的事件發生時觸發。關閉連接的時候會觸發connectionLost事件函數

(Simple, single-use clients)簡單的單用戶客戶端
? 在許多情況下,protocol僅僅是需要連接服務器一次,并且代碼僅僅是要獲得一個protocol連接的實例。在
這樣的情況下,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)


          


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是在Connection不能被建立的時候調用,clientConnectionLost是在連接關閉的時候被調用,兩個是有區別的。


Reconnection(重新連接)
? 許多時候,客戶端連接可能由于網絡錯誤經常被斷開。一個重新建立連接的方法是在連接斷開的時候調用

connector.connect()方法。

            
from twisted.internet.protocol import ClientFactory

class 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, 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)


          


A Higher-Level Example: ircLogBot
上面的所有例子都非常簡單,下面是一個比較復雜的例子來自于doc/examples目錄

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

# system imports
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 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 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會獲得他本身的一個實例的引用。然后,就能夠在factory中存在他的屬性。

更多的信息:
? 本文檔講述的Protocol類是IProtocol的子類,IProtocol方便的被應用在大量的twisted應用程序中。要學習完整的 IProtocol接口,請參考API文檔IProtocol.
? 在本文檔一些例子中使用的trasport屬性提供了ITCPTransport接口,要學習完整的接口,請參考API文檔ITCPTransport
? 接口類是指定對象有什么方法和屬性以及他們的表現形式的一種方法。參考 Components: Interfaces and Adapters文檔


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 丹阳市| 香格里拉县| 宣汉县| 南平市| 和平区| 湘乡市| 县级市| 西乌珠穆沁旗| 盘锦市| 大安市| 香河县| 宁明县| 九江市| 宁河县| 泸溪县| 丹东市| 平塘县| 珲春市| 曲沃县| 唐河县| 乌苏市| 盐城市| 苗栗市| 招远市| 湛江市| 保定市| 上饶市| 彭泽县| 五台县| 洪泽县| 禄劝| 怀柔区| 金寨县| 大宁县| 山阳县| 尼玛县| 临清市| 长宁区| 阿克陶县| 都江堰市| 二连浩特市|