Utilities/BackgroundClient.py

branch
BgService
changeset 3417
5a93c6cdc989
parent 3241
957673fc463a
child 3444
118cb489304d
equal deleted inserted replaced
3415:180ae0154322 3417:5a93c6cdc989
10 """ 10 """
11 11
12 from __future__ import unicode_literals 12 from __future__ import unicode_literals
13 try: 13 try:
14 bytes = unicode 14 bytes = unicode
15 import StringIO as io # __IGNORE_EXCEPTION__
15 except NameError: 16 except NameError:
16 pass 17 import io # __IGNORE_WARNING__
17 18
18 import json 19 import json
19 import socket 20 import socket
20 import struct 21 import struct
21 import sys 22 import sys
23 import traceback
22 from zlib import adler32 24 from zlib import adler32
23 25
24 26
25 class BackgroundClient(object): 27 class BackgroundClient(object):
26 """ 28 """
36 self.services = {} 38 self.services = {}
37 39
38 self.connection = socket.create_connection((host, port)) 40 self.connection = socket.create_connection((host, port))
39 ver = b'Python2' if sys.version_info[0] == 2 else b'Python3' 41 ver = b'Python2' if sys.version_info[0] == 2 else b'Python3'
40 self.connection.sendall(ver) 42 self.connection.sendall(ver)
41 self.connection.settimeout(0.25)
42 43
43 def __initClientService(self, fn, path, module): 44 def __initClientService(self, fn, path, module):
44 """ 45 """
45 Import the given module and register it as service. 46 Import the given module and register it as service.
46 47
75 76
76 def run(self): 77 def run(self):
77 """ 78 """
78 Implement the main loop of the client. 79 Implement the main loop of the client.
79 """ 80 """
80 while True: 81 try:
81 try: 82 while True:
82 header = self.connection.recv(8) # __IGNORE_EXCEPTION__ 83 try:
83 except socket.timeout: 84 header = b''
84 continue 85 while len(header) < 8:
85 except socket.error: 86 header += self.connection.recv(8 - len(header))
87 except socket.error:
88 # Leave main loop if connection was closed.
89 break
86 # Leave main loop if connection was closed. 90 # Leave main loop if connection was closed.
87 break 91 if not header:
88 # Leave main loop if connection was closed. 92 break
89 if not header: 93
90 break 94 length, datahash = struct.unpack(b'!II', header)
91 95 packedData = b''
92 length, datahash = struct.unpack(b'!II', header) 96 while len(packedData) < length:
93 packedData = b'' 97 packedData += self.connection.recv(
94 while len(packedData) < length: 98 length - len(packedData))
95 packedData += self.connection.recv(length - len(packedData)) 99
96 100 assert adler32(packedData) & 0xffffffff == datahash, \
97 assert adler32(packedData) & 0xffffffff == datahash, \ 101 'Hashes not equal'
98 'Hashes not equal' 102 if sys.version_info[0] == 3:
99 if sys.version_info[0] == 3: 103 packedData = packedData.decode('utf-8')
100 packedData = packedData.decode('utf-8') 104
101 105 fx, fn, data = json.loads(packedData)
102 fx, fn, data = json.loads(packedData) 106 if fx == 'INIT':
103 if fx == 'INIT': 107 ret = self.__initClientService(fn, *data)
104 ret = self.__initClientService(fn, *data)
105 else:
106 callback = self.services.get(fx)
107 if callback:
108 ret = callback(fn, *data)
109 else: 108 else:
110 ret = 'Unknown service.' 109 callback = self.services.get(fx)
111 110 if callback:
112 self.__send(fx, fn, ret) 111 ret = callback(fn, *data)
113 112 else:
113 ret = 'Unknown service.'
114
115 self.__send(fx, fn, ret)
116 except:
117 exctype, excval, exctb = sys.exc_info()
118 tbinfofile = io.StringIO()
119 traceback.print_tb(exctb, None, tbinfofile)
120 tbinfofile.seek(0)
121 tbinfo = tbinfofile.read()
122 del exctb
123 self.__send(
124 'EXCEPTION', '?', [str(exctype), str(excval), tbinfo])
125
126 self.connection.shutdown(socket.SHUT_RDWR)
114 self.connection.close() 127 self.connection.close()
115 sys.exit()
116
117 def __unhandled_exception(self, exctype, excval, exctb):
118 """
119 Private method called to report an uncaught exception.
120
121 @param exctype the type of the exception
122 @param excval data about the exception
123 @param exctb traceback for the exception
124 """
125 # TODO: Wrap arguments so they can be serialized by JSON
126 self.__send(
127 'EXCEPTION', '?', [str(exctype), str(excval), str(exctb)])
128 128
129 if __name__ == '__main__': 129 if __name__ == '__main__':
130 if len(sys.argv) != 3: 130 if len(sys.argv) != 3:
131 print('Host and port parameters are missing. Abort.') 131 print('Host and port parameters are missing. Abort.')
132 sys.exit(1) 132 sys.exit(1)
133 133
134 host, port = sys.argv[1:] 134 host, port = sys.argv[1:]
135 backgroundClient = BackgroundClient(host, int(port)) 135 backgroundClient = BackgroundClient(host, int(port))
136 # set the system exception handling function to ensure, that
137 # we report on all unhandled exceptions
138 sys.excepthook = backgroundClient._BackgroundClient__unhandled_exception
139 # Start the main loop 136 # Start the main loop
140 backgroundClient.run() 137 backgroundClient.run()

eric ide

mercurial