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 b'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 class FingerSetterProtocol(basic.LineReceiver):
28 def connectionMade(self):
29 self.lines = []
30
31 def lineReceived(self, line):
32 self.lines.append(line)
33
34 def connectionLost(self, reason):
35 user = self.lines[0]
36 status = self.lines[1]
37 self.factory.setUser(user, status)
38
39 class FingerSetterFactory(protocol.ServerFactory):
40 protocol = FingerSetterProtocol
41
42 def __init__(self, fingerFactory):
43 self.fingerFactory = fingerFactory
44
45 def setUser(self, user, status):
46 self.fingerFactory.users[user] = status
47
48 ff = FingerFactory({b'moshez': b'Happy and well'})
49 fsf = FingerSetterFactory(ff)
50
51 application = service.Application('finger', uid=1, gid=1)
52 serviceCollection = service.IServiceCollection(application)
53 strports.service("tcp:79", ff).setServiceParent(serviceCollection)
54 strports.service("tcp:1079", fsf).setServiceParent(serviceCollection)
這個項目有兩個協定-工廠類,每一個都是application的子程式。更具體地說,setServiceParents方法把兩個服務定義為application,實作了IServiceCollections。這兩個服務都由應用程式啟動。
使用Services讓依賴更加合理
使用服務基類,實作泛型行為
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 b'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 FingerSetterProtocol(basic.LineReceiver):
19 def connectionMade(self):
20 self.lines = []
21
22 def lineReceived(self, line):
23 self.lines.append(line)
24
25 def connectionLost(self,reason):
26 user = self.lines[0]
27 status = self.lines[1]
28 self.factory.setUser(user, status)
29
30 class FingerService(service.Service):
31 def __init__(self, users):
32 self.users = users
33
34 def getUser(self, user):
35 return defer.succeed(self.users.get(user, b"No such user"))
36
37 def setUser(self, user, status):
38 self.users[user] = status
39
40 def getFingerFactory(self):
41 f = protocol.ServerFactory()
42 f.protocol = FingerProtocol
43 f.getUser = self.getUser
44 return f
45
46 def getFingerSetterFactory(self):
47 f = protocol.ServerFactory()
48 f.protocol = FingerSetterProtocol
49 f.setUser = self.setUser
50 return f
51
52 application = service.Application('finger', uid=1, gid=1)
53 f = FingerService({b'moshez': b'Happy and well'})
54 serviceCollection = service.IServiceCollection(application)
55 strports.service("tcp:79", f.getFingerFactory()
56 ).setServiceParent(serviceCollection)
57 strports.service("tcp:1079", f.getFingerSetterFactory()
58 ).setServiceParent(serviceCollection)
簡化了代碼,在一個服務中使用兩個協定 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 b'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
19 class FingerService(service.Service):
20 def __init__(self, filename):
21 self.users = {}
22 self.filename = filename
23
24 def _read(self):
25 with open(self.filename, "rb") as f:
26 for line in f:
27 user, status = line.split(b':', 1)
28 user = user.strip()
29 status = status.strip()
30 self.users[user] = status
#這裡每30秒重新整理一次
31 self.call = reactor.callLater(30, self._read)
32
33 def startService(self):
34 self._read()
35 service.Service.startService(self)
36
37 def stopService(self):
38 service.Service.stopService(self)
39 self.call.cancel()
40
41 def getUser(self, user):
42 return defer.succeed(self.users.get(user, b"No such user"))
43
44 def getFingerFactory(self):
45 f = protocol.ServerFactory()
46 f.protocol = FingerProtocol
47 f.getUser = self.getUser
48 return f
49
50
51 application = service.Application('finger', uid=1, gid=1)
52 f = FingerService('/etc/users')
53 finger = strports.service("tcp:79", f.getFingerFactory())
54
55 finger.setServiceParent(service.IServiceCollection(application))
56 f.setServiceParent(service.IServiceCollection(application))
這個版本在一個集中管理的檔案中讀取消息,而且進行緩存,每30秒重新整理一次
在網上進行宣布
也有其他的服務可以産生這種有效的通信。舉個例子,在twisted.web裡,這個類本身不做基類,而是被給一個資源,表示通過URL可用的樹形資源。這個層級結構由Site動态地覆寫,通過getChild。
為了把它集合到Finger應用程式裡,我們設定一個新的TCPservice,這個伺服器調用Site的心函數來擷取資源。
1 from twisted.application import service, strports
2 from twisted.internet import protocol, reactor, defer
3 from twisted.protocols import basic
4 from twisted.web import resource,server,static
5 import cgi
6
7 class FingerProtocol(basic.LineReceiver):
8 def lineReceived(self, user):
9 d = self.factory.getUser(user)
10
11 def onError(err):
12 return b'Internal error in server'
13 d.addErrback(onError)
14
15 def writeResponse(message):
16 self.transport.write(message + b'\r\n')
17 self.transport.loseConnection()
18 d.addCallback(writeResponse)
19
20 class FingerResource(resource.Resource):
21 def __init__(self,users):
22 self.users=users
23 #繼承基類的__init__
24 super(FingerResource, self).__init__()
25 def getChild(self, path, request):
26 messageValue=self.users.get(path)
27 if messageValue:
28 messageValue=messageValue.decode('ascii')
29 if path:
30 path=path.decode('ascii')
31 if messageValue is not None:
32 messageValue=cgi.escape(messageValue)
33 text="<h1>{}</h1><p>{}</p>".format(path,messageValue)
34 else:
35 text="<h1>{}</h1><p>no such path</p>".format(path)
36 text=text.encode('ascii')
37 return static.Data(text,'text/html')
38 class FingerService(service.Service):
39 def __init__(self,filename):
40 self.filename=filename
41 self.users={}
42 def _read(self):
43 self.users.clear()
44 with open(self.filename,'rb')as f:
45 for line in f:
46 user,status=line.split(b":",1)
47 user=user.strip()
48 status=status.strip()
49 self.users[user]=status
50 self.call=reactor.callLater(30,self._reaf)
51 def getUser(self,user):
52 return defer.succeed(self.users.get(user,b'no such user'))
53 def getFingerFactory(self):
54 f=protocol.ServerFactory()
55 f.protocol=FingerProtocol
56 f.getUser=self.getUser
57 return f
58 def getResource(self):
59 f=FingerResource(self.users)
60 return f
61 def startService(self):
62 self._read()
63 service.Service.stopService(self)
64 def stopService(self):
65 service.Service.stopService(self)
66 self.call.cancel()
67 application=service.Application('finger',uid=1,gid=1)
68 f=FingerService('/finger')
69 serviceCollection=service.IServiceCollection(application)
70 f.setServiceParent(serviceCollection)
71 strports.service("tcp:79",f.getFingerFactory()
72 ).setServiceParent(serviceCollection)
73 strports.service("tcp:8000",server.Site(f.getResource())
74 ).setServiceParent(serviceCollection)
在IRC上宣布
IRC用戶端通常很像伺服器,相應來自網咯的時間。客戶服務獎確定切斷的連接配接重建立立,用了很常見的指數退避。
1 from twisted.application import internet, service, strports
2 from twisted.internet import protocol, reactor, defer, endpoints
3 from twisted.words.protocols import irc
4 from twisted.protocols import basic
5 from twisted.web import resource, server, static
6
7 import cgi
8
9 class FingerProtocol(basic.LineReceiver):
10 def lineReceived(self, user):
11 d = self.factory.getUser(user)
12
13 def onError(err):
14 return b'Internal error in server'
15 d.addErrback(onError)
16
17 def writeResponse(message):
18 self.transport.write(message + b'\r\n')
19 self.transport.loseConnection()
20 d.addCallback(writeResponse)
21
22
23 class IRCReplyBot(irc.IRCClient):
24 def connectionMade(self):
25 self.nickname = self.factory.nickname
26 irc.IRCClient.connectionMade(self)
27
28 def privmsg(self, user, channel, msg):
29 user = user.split('!')[0]
30 if self.nickname.lower() == channel.lower():
31 d = self.factory.getUser(msg.encode("ascii"))
32
33 def onError(err):
34 return b'Internal error in server'
35 d.addErrback(onError)
36
37 def writeResponse(message):
38 message = message.decode("ascii")
39 irc.IRCClient.msg(self, user, msg + ': ' + message)
40 d.addCallback(writeResponse)
41
42
43 class FingerService(service.Service):
44 def __init__(self, filename):
45 self.filename = filename
46 self.users = {}
47
48 def _read(self):
49 self.users.clear()
50 with open(self.filename, "rb") as f:
51 for line in f:
52 user, status = line.split(b':', 1)
53 user = user.strip()
54 status = status.strip()
55 self.users[user] = status
56 self.call = reactor.callLater(30, self._read)
57
58 def getUser(self, user):
59 return defer.succeed(self.users.get(user, b"No such user"))
60
61 def getFingerFactory(self):
62 f = protocol.ServerFactory()
63 f.protocol = FingerProtocol
64 f.getUser = self.getUser
65 return f
66
67 def getResource(self):
68 def getData(path, request):
69 user = self.users.get(path, b"No such users <p/> usage: site/user")
70 path = path.decode("ascii")
71 user = user.decode("ascii")
72 text = '<h1>{}</h1><p>{}</p>'.format(path, user)
73 text = text.encode("ascii")
74 return static.Data(text, 'text/html')
75
76 r = resource.Resource()
77 r.getChild = getData
78 return r
79
80 def getIRCBot(self, nickname):
81 f = protocol.ClientFactory()
82 f.protocol = IRCReplyBot
83 f.nickname = nickname
84 f.getUser = self.getUser
85 return f
86
87 def startService(self):
88 self._read()
89 service.Service.startService(self)
90
91 def stopService(self):
92 service.Service.stopService(self)
93 self.call.cancel()
94
95
96 application = service.Application('finger', uid=1, gid=1)
97 f = FingerService('/etc/users')
98 serviceCollection = service.IServiceCollection(application)
99 f.setServiceParent(serviceCollection)
100 strports.service("tcp:79", f.getFingerFactory()
101 ).setServiceParent(serviceCollection)
102 strports.service("tcp:8000", server.Site(f.getResource())
103 ).setServiceParent(serviceCollection)
104 internet.ClientService(
105 endpoints.clientFromString(reactor, "tcp:irc.freenode.org:6667"),
106 f.getIRCBot('fingerbot')).setServiceParent(serviceCollection)
轉載于:https://www.cnblogs.com/losenine/p/10084572.html