-
Notifications
You must be signed in to change notification settings - Fork 0
/
jsonsocket.py
127 lines (104 loc) · 2.98 KB
/
jsonsocket.py
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
121
122
123
124
125
126
127
import json, socket
class Server(object):
"""
A JSON socket server used to communicate with a JSON socket client. All the
data is serialized in JSON. How to use it:
server = Server(host, port)
while True:
server.accept()
data = server.recv()
# shortcut: data = server.accept().recv()
server.send({'status': 'ok'})
"""
backlog = 5
client = None
def __init__(self, host, port):
self.socket = socket.socket()
self.socket.bind((host, port))
self.socket.listen(self.backlog)
def __del__(self):
self.close()
def accept(self):
# if a client is already connected, disconnect it
if self.client:
self.client.close()
self.client, self.client_addr = self.socket.accept()
return self
def send(self, data):
if not self.client:
raise Exception('Cannot send data, no client is connected')
_send(self.client, data)
return self
def recv(self):
if not self.client:
raise Exception('Cannot receive data, no client is connected')
return _recv(self.client)
def close(self):
if self.client:
self.client.close()
self.client = None
if self.socket:
self.socket.close()
self.socket = None
class Client(object):
"""
A JSON socket client used to communicate with a JSON socket server. All the
data is serialized in JSON. How to use it:
data = {
'name': 'Patrick Jane',
'age': 45,
'children': ['Susie', 'Mike', 'Philip']
}
client = Client()
client.connect(host, port)
client.send(data)
response = client.recv()
# or in one line:
response = Client().connect(host, port).send(data).recv()
"""
socket = None
def __del__(self):
self.close()
def connect(self, host, port):
self.socket = socket.socket()
self.socket.connect((host, port))
self.socket.settimeout(3)
return self
def send(self, data):
if not self.socket:
raise Exception('You have to connect first before sending data')
_send(self.socket, data)
return self
def recv(self):
if not self.socket:
raise Exception('You have to connect first before receiving data')
return _recv(self.socket)
def recv_and_close(self):
data = self.recv()
self.close()
return data
def close(self):
if self.socket:
self.socket.close()
self.socket = None
## helper functions ##
def _send(socket, data):
try:
serialized = json.dumps(data)
except (TypeError, ValueError) as e:
raise Exception('You can only send JSON-serializable data')
# print(f'serialized type {type(serialized)}')
b = bytes( serialized + '\n', 'ascii')
socket.sendall(b)
def _recv(socket):
# read the length of the data, letter by letter until we reach EOL
data_in = ''
char = socket.recv(1).decode('ascii')
while char != '\n':
data_in += char
char = socket.recv(1).decode('ascii')
try:
deserialized = json.loads(data_in)
except (TypeError, ValueError) as e:
raise Exception('Data received was not in JSON format')
return deserialized