使用Python的Twisted框架编写简单的网络客户端
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() 本协议连接到服务器,发送了一个问候消息,然后关闭了连接。 (Simple,single-use clients)简单的单用户客户端 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)
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,reason): print 'Connection failed. Reason:',reason 要想将EchoClientFactory连接到服务器,可以使用下面代码: from twisted.internet import reactor reactor.connectTCP(host,port,EchoClientFactory()) reactor.run() 注意:clientConnectionFailed是在Connection不能被建立的时候调用,clientConnectionLost是在连接关闭的时候被调用,两个是有区别的。
connector.connect()方法。 from twisted.internet.protocol import ClientFactory class EchoClientFactory(ClientFactory): def clientConnectionLost(self,reason): connector.connect() connector是connection和protocol之间的一个接口被作为第一个参数传递给clientConnectionLost, factory能调用connector.connect()方法重新进行连接 函数,并且不断的尝试重新连接。这里有一个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,reason ReconnectingClientFactory.clientConnectionLost(self,reason) def clientConnectionFailed(self,reason ReconnectingClientFactory.clientConnectionFailed(self,reason)
# 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,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,filename): self.channel = channel self.filename = filename def clientConnectionLost(self,reason): """If we get disconnected,reconnect to server.""" connector.connect() def clientConnectionFailed(self,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 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,filename): self.channel = channel self.filename = filename 当protocol被创建之后,factory会获得他本身的一个实例的引用。然后,就能够在factory中存在他的属性。 更多的信息: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |