Skip to content

Commit 1360a2b

Browse files
author
Dave P
committed
performance tweaks
1 parent ee67edc commit 1360a2b

File tree

3 files changed

+102
-82
lines changed

3 files changed

+102
-82
lines changed

README.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Supports
66

77
Passes Autobahn Websocket Testsuite
88

9-
<h4>Simple Echo Server Example</h4>
9+
<h4>Echo Server Example</h4>
1010
`````python
1111
from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer
1212

@@ -28,6 +28,30 @@ Passes Autobahn Websocket Testsuite
2828

2929
Open <i>websocket.html</i> and connect to the server.
3030

31+
<h4>Chat Server Example</h4>
32+
`````python
33+
clients = []
34+
class SimpleChat(WebSocket):
35+
36+
def handleMessage(self):
37+
for client in list(clients):
38+
if client != self:
39+
client.sendMessage(self.address[0] + ' - ' + self.data)
40+
41+
def handleConnected(self):
42+
print self.address, 'connected'
43+
for client in list(clients):
44+
client.sendMessage(self.address[0] + u' - connected')
45+
clients.append(self)
46+
47+
def handleClose(self):
48+
clients.remove(self)
49+
print self.address, 'closed'
50+
for client in list(clients):
51+
client.sendMessage(self.address[0] + u' - disconnected')
52+
`````
53+
Open multiple <i>websocket.html</i> and connect to the server.
54+
3155
<h4>Want to get up and running faster?</h4>
3256

3357
There is an example which provides a simple echo and chat server

SimpleWebSocketServer/SimpleExampleServer.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,26 @@ def handleConnected(self):
1919
def handleClose(self):
2020
pass
2121

22-
22+
clients = []
2323
class SimpleChat(WebSocket):
2424

2525
def handleMessage(self):
26-
for client in self.server.connections.itervalues():
26+
for client in list(clients):
2727
if client != self:
2828
client.sendMessage(self.address[0] + ' - ' + self.data)
2929

3030
def handleConnected(self):
3131
print self.address, 'connected'
32-
for client in self.server.connections.itervalues():
33-
if client != self:
34-
client.sendMessage(self.address[0] + u' - connected')
35-
32+
for client in list(clients):
33+
client.sendMessage(self.address[0] + u' - connected')
34+
clients.append(self)
35+
3636
def handleClose(self):
37+
clients.remove(self)
3738
print self.address, 'closed'
38-
for client in self.server.connections.itervalues():
39-
if client != self:
40-
client.sendMessage(self.address[0] + u' - disconnected')
41-
39+
for client in list(clients):
40+
client.sendMessage(self.address[0] + u' - disconnected')
41+
4242

4343
if __name__ == "__main__":
4444

SimpleWebSocketServer/SimpleWebSocketServer.py

Lines changed: 67 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import socket
99
import struct
1010
import ssl
11-
import time
1211
import sys
1312
import errno
1413
import codecs
@@ -151,75 +150,74 @@ def _handlePacket(self):
151150
status = 1002
152151

153152
self.close(status, reason)
154-
#raise Exception("received client close")
153+
return
155154

156-
if self.fin == 0:
157-
if self.opcode != STREAM:
158-
if self.opcode == PING or self.opcode == PONG:
159-
raise Exception('control messages can not be fragmented')
160-
161-
self.frag_type = self.opcode
162-
self.frag_start = True
163-
self.frag_decoder.reset()
164-
165-
if self.frag_type == TEXT:
166-
self.frag_buffer = u''
167-
utf_str = self.frag_decoder.decode(self.data, final = False)
168-
if utf_str:
169-
self.frag_buffer += utf_str
170-
else:
171-
self.frag_buffer = bytearray()
172-
self.frag_buffer += self.data
173-
174-
else:
175-
if self.frag_start is False:
176-
raise Exception('fragmentation protocol error')
177-
178-
if self.frag_type == TEXT:
179-
utf_str = self.frag_decoder.decode(self.data, final = False)
180-
if utf_str:
181-
self.frag_buffer += utf_str
182-
else:
183-
self.frag_buffer += self.data
155+
elif self.fin == 0:
156+
if self.opcode != STREAM:
157+
if self.opcode == PING or self.opcode == PONG:
158+
raise Exception('control messages can not be fragmented')
159+
160+
self.frag_type = self.opcode
161+
self.frag_start = True
162+
self.frag_decoder.reset()
163+
164+
if self.frag_type == TEXT:
165+
self.frag_buffer = []
166+
utf_str = self.frag_decoder.decode(self.data, final = False)
167+
if utf_str:
168+
self.frag_buffer.append(utf_str)
169+
else:
170+
self.frag_buffer = bytearray()
171+
self.frag_buffer.extend(self.data)
172+
173+
else:
174+
if self.frag_start is False:
175+
raise Exception('fragmentation protocol error')
176+
177+
if self.frag_type == TEXT:
178+
utf_str = self.frag_decoder.decode(self.data, final = False)
179+
if utf_str:
180+
self.frag_buffer.append(utf_str)
181+
else:
182+
self.frag_buffer.extend(self.data)
184183

185-
else:
186-
187-
if self.opcode == STREAM:
188-
if self.frag_start is False:
189-
raise Exception('fragmentation protocol error')
190-
191-
if self.frag_type == TEXT:
192-
utf_str = self.frag_decoder.decode(self.data, final = True)
193-
self.frag_buffer += utf_str
194-
else:
195-
self.frag_buffer += self.data
196-
197-
self.data = self.frag_buffer
184+
else:
185+
if self.opcode == STREAM:
186+
if self.frag_start is False:
187+
raise Exception('fragmentation protocol error')
188+
189+
if self.frag_type == TEXT:
190+
utf_str = self.frag_decoder.decode(self.data, final = True)
191+
self.frag_buffer.append(utf_str)
192+
self.data = u''.join(self.frag_buffer)
193+
else:
194+
self.frag_buffer.extend(self.data)
195+
self.data = self.frag_buffer
196+
197+
self.handleMessage()
198+
199+
self.frag_decoder.reset()
200+
self.frag_type = BINARY
201+
self.frag_start = False
202+
self.frag_buffer = None
203+
204+
elif self.opcode == PING:
205+
self._sendMessage(False, PONG, self.data)
206+
207+
elif self.opcode == PONG:
208+
pass
198209

199-
self.handleMessage()
200-
201-
self.frag_decoder.reset()
202-
self.frag_type = BINARY
203-
self.frag_start = False
204-
self.frag_buffer = None
205-
206-
elif self.opcode == PING:
207-
self._sendMessage(False, PONG, self.data)
208-
209-
elif self.opcode == PONG:
210-
pass
211-
212-
else:
213-
if self.frag_start is True:
214-
raise Exception('fragmentation protocol error')
215-
216-
if self.opcode == TEXT:
217-
try:
218-
self.data = self.data.decode('utf-8', errors='strict')
219-
except Exception as exp:
220-
raise Exception('invalid utf-8 payload')
221-
222-
self.handleMessage()
210+
else:
211+
if self.frag_start is True:
212+
raise Exception('fragmentation protocol error')
213+
214+
if self.opcode == TEXT:
215+
try:
216+
self.data = self.data.decode('utf-8', errors='strict')
217+
except Exception as exp:
218+
raise Exception('invalid utf-8 payload')
219+
220+
self.handleMessage()
223221

224222

225223
def _handleData(self):
@@ -255,14 +253,13 @@ def _handleData(self):
255253

256254
# else do normal data
257255
else:
258-
data = self.client.recv(2048)
256+
data = self.client.recv(8192)
259257
if not data:
260258
raise Exception("remote socket closed")
261259

262260
for d in data:
263261
self._parseMessage(ord(d))
264262

265-
266263
def close(self, status = 1000, reason = u''):
267264
"""
268265
Send Close frame to the client. The underlying socket is only closed
@@ -303,8 +300,7 @@ def _sendBuffer(self, buff):
303300

304301
except socket.error as e:
305302
# if we have full buffers then wait for them to drain and try again
306-
if e.errno == errno.EAGAIN:
307-
#time.sleep(0.001)
303+
if e.errno in [errno.EAGAIN, errno.EWOULDBLOCK]:
308304
return buff[already_sent:]
309305
else:
310306
raise e

0 commit comments

Comments
 (0)