3..Twisted学习

发布时间:2019-04-17 21:35:11编辑:auto阅读(1930)

    写这个主要是为了自己理解Twisted的文档

    建立一个finger服务

    你不需要调用Twisted,Twisted会自己运行。reactor是Twisted的主循环,想python的其他主循环一样。每个Twisted只有一个reactor。一旦启动他就会不停的运行下去,响应一个又一个请求。

    from twisted.internet import reactor返回当前的reactor。如果你不选择一个reactor的话,它会默认选择。

     1 from twisted.internet import protocol, reactor, endpoints
     2 
     3 class FingerProtocol(protocol.Protocol):
     4     pass
     5 
     6 class FingerFactory(protocol.ServerFactory):
     7     protocol = FingerProtocol
     8 
     9 fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
    10 fingerEndpoint.listen(FingerFactory())
    11 reactor.run()

    这个流程看过前两章的应该很熟悉了,先创建协议,再创建工厂,然后主循环。

     1 from twisted.internet import protocol, reactor, endpoints
     2 
     3 class FingerProtocol(protocol.Protocol):
     4     def connectionMade(self):
     5         self.transport.loseConnection()
     6 
     7 class FingerFactory(protocol.ServerFactory):
     8     protocol = FingerProtocol
     9 
    10 fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
    11 fingerEndpoint.listen(FingerFactory())
    12 reactor.run()

    这个是增加了一个连接之后的初始化配置

     1 from twisted.internet import protocol, reactor, endpoints
     2 from twisted.protocols import basic
     3 
     4 class FingerProtocol(basic.LineReceiver):
     5     def lineReceived(self, user):
     6         self.transport.loseConnection()
     7 
     8 class FingerFactory(protocol.ServerFactory):
     9     protocol = FingerProtocol
    10 
    11 fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
    12 fingerEndpoint.listen(FingerFactory())
    13 reactor.run()

    这个是按行读取数据,就是按照你的\r\n读取数据,之后关闭连接

    写一个读取用户名,返回错误,断开连接的finger

     1 from twisted.internet import protocol, reactor, endpoints
     2 from twisted.protocols import basic
     3 
     4 class FingerProtocol(basic.LineReceiver):
     5     def lineReceived(self, user):
     6         self.transport.write(b"No such user\r\n")
     7         self.transport.loseConnection()
     8 
     9 class FingerFactory(protocol.ServerFactory):
    10     protocol = FingerProtocol
    11 
    12 fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
    13 fingerEndpoint.listen(FingerFactory())
    14 reactor.run()

    这个就是按行读取,返回一句话,之后关闭连接

     1 from twisted.internet import protocol, reactor, endpoints
     2 from twisted.protocols import basic
     3 
     4 class FingerProtocol(basic.LineReceiver):
     5     def lineReceived(self, user):
     6         self.transport.write(self.factory.getUser(user)+ b"\r\n")
     7         self.transport.loseConnection()
     8 
     9 class FingerFactory(protocol.ServerFactory):
    10     protocol = FingerProtocol
    11 
    12     def getUser(self, user):
    13         return b"No such user"
    14 
    15 fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
    16 fingerEndpoint.listen(FingerFactory())
    17 reactor.run()

    增加获取用户名的函数

    在协议之中调用工厂方法,可以用self.factory,这个就是指向工厂的,因为工厂类实际上是它的父类。

     1 from twisted.internet import protocol, reactor, endpoints
     2 from twisted.protocols import basic
     3 
     4 class FingerProtocol(basic.LineReceiver):
     5     def lineReceived(self, user):
     6         self.transport.write(self.factory.getUser(user) + b"\r\n")
     7         self.transport.loseConnection()
     8 
     9 class FingerFactory(protocol.ServerFactory):
    10     protocol = FingerProtocol
    11 
    12     def __init__(self, users):
    13         self.users = users
    14 
    15     def getUser(self, user):
    16         return self.users.get(user, b"No such user")
    17 
    18 fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
    19 fingerEndpoint.listen(FingerFactory({ b'moshez' : b'Happy and well'}))
    20 reactor.run()

    初始化一个字典,如果你输入的用户名没有在字典里边,就会返回默认值。

    Defereds

     

     1 from twisted.internet import protocol, reactor, defer, endpoints
     2 from twisted.protocols import basic
     3 
     4 class FingerProtocol(basic.LineReceiver):
     5     def lineReceived(self, user):
     6         d = self.factory.getUser(user)
     7 
     8         def onError(err):
     9             return 'Internal error in server'
    10         d.addErrback(onError)
    11 
    12         def writeResponse(message):
    13             self.transport.write(message + b'\r\n')
    14             self.transport.loseConnection()
    15         d.addCallback(writeResponse)
    16 
    17 class FingerFactory(protocol.ServerFactory):
    18     protocol = FingerProtocol
    19 
    20     def __init__(self, users):
    21         self.users = users
    22 
    23     def getUser(self, user):
    24         return defer.succeed(self.users.get(user, b"No such user"))
    25 
    26 fingerEndpoint = endpoints.serverFromString(reactor, "tcp:1079")
    27 fingerEndpoint.listen(FingerFactory({b'moshez': b'Happy and well'}))
    28 reactor.run()

     

    在这个里边,我么使用了defer,其实也就仅仅修改了getUser方法。Defereds循序由事件驱动程序,也就是说,如果程序中的一个任务正在等待数据,程序可以去执行其他操作,这叫做异步执行。

    上边的代码测试了一下,是按照队列执行的,就是说两个客户端发送数据,如果第一个客户端设置延迟返回5秒,那么之后5秒后,第二个客户端才会被响应。

    解释一下deferred:

    大家可以去看

    https://www.cnblogs.com/zhangjing0502/archive/2012/05/16/2504415.html  作者:很多不懂呀。。

    Twisted

     1 from twisted.application import service, strports
     2 from twisted.internet import protocol, reactor, defer
     3 from twisted.protocols import basic
     4 
     5 class FingerProtocol(basic.LineReceiver):
     6     def lineReceived(self, user):
     7         d = self.factory.getUser(user)
     8 
     9         def onError(err):
    10             return 'Internal error in server'
    11         d.addErrback(onError)
    12 
    13         def writeResponse(message):
    14             self.transport.write(message + b'\r\n')
    15             self.transport.loseConnection()
    16         d.addCallback(writeResponse)
    17 
    18 class FingerFactory(protocol.ServerFactory):
    19     protocol = FingerProtocol
    20 
    21     def __init__(self, users):
    22         self.users = users
    23 
    24     def getUser(self, user):
    25         return defer.succeed(self.users.get(user, b"No such user"))
    26 
    27 application = service.Application('finger', uid=1, gid=1)
    28 factory = FingerFactory({b'moshez': b'Happy and well'})
    29 strports.service("tcp:79", factory, reactor=reactor).setServiceParent(
    30     service.IServiceCollection(application))

    可能你已经发现了,我们的协议类从上边开始就没变过,事实上,以后也很少会变了,主要是在工厂里更改。

    这个例子是告诉twisted您的应用程序在哪里,使用的是application

    from twisted.application import service,strports

    在这里我们没有再使用serverFormString来设置地址端口,我们用了他的应用程序来启动,strports.service。注意,当它被实例化的时候,这个程序对象不会引用协议和工厂!

    任何把application当做父对象的服务将会在twisted启动的时候被启动。总之,他就是来管理启动服务和关闭服务的。

     

关键字