gpt4 book ai didi

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

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章使用Python的Twisted框架编写简单的网络客户端由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

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

?
1
2
3
4
5
6
from twisted.internet.protocol import Protocol
from sys import stdout
 
class Echo(Protocol):
   def dataReceived( self , data):
     stdout.write(data)

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

?
1
2
3
4
5
6
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 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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协议并且打印当前的连接状态 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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连接到服务器,可以使用下面代码:

?
1
2
3
from twisted.internet import reactor
reactor.connectTCP(host, port, EchoClientFactory())
reactor.run()

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

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

connector.connect()方法.

?
1
2
3
4
5
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的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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目录 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# 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在每次连接的时候重建,客户端需要以某种方式来记录数据以保证持久化。就好像日志机器人一样他需要知道那个那个频道正在登陆,登陆到什么地方去.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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文档 。

最后此篇关于使用Python的Twisted框架编写简单的网络客户端的文章就讲到这里了,如果你想了解更多关于使用Python的Twisted框架编写简单的网络客户端的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com