Skip to content

Commit 5d3bf4c

Browse files
committed
Merge pull request Lawouach#5 from progrium/master
Added a gevent client and fixed a major flaw in the gevent/"wsgi" server handler
2 parents 9a6c2b6 + d321c8f commit 5d3bf4c

6 files changed

Lines changed: 136 additions & 185 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
build
12
*.egg-info

ws4py/client/geventclient.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# -*- coding: utf-8 -*-
2+
from urlparse import urlsplit
3+
import copy
4+
5+
import gevent
6+
from gevent import Greenlet
7+
from gevent import socket
8+
from gevent.coros import Semaphore
9+
from gevent.queue import Queue
10+
11+
from ws4py.client.threadedclient import WebSocketClient as ThreadedClient
12+
from ws4py.exc import HandshakeError, StreamClosed
13+
14+
__all__ = ['WebSocketClient']
15+
16+
class WebSocketClient(ThreadedClient):
17+
def __init__(self, url, protocols=None, version='8'):
18+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
19+
ThreadedClient.__init__(self, url, protocols=protocols, version=version, sock=sock)
20+
21+
self._lock = Semaphore()
22+
self._th = Greenlet(self._receive)
23+
self._messages = Queue()
24+
25+
self.extensions = []
26+
27+
def opened(self, protocols, extensions):
28+
self.protocols = protocols
29+
self.extensions = extensions
30+
31+
def received_message(self, m):
32+
self._messages.put(copy.deepcopy(m))
33+
34+
def write_to_connection(self, bytes):
35+
if not self.client_terminated:
36+
return self.sock.sendall(bytes)
37+
38+
def closed(self, code, reason=None):
39+
self._messages.put(StreamClosed(code, reason))
40+
41+
def receive(self, msg_obj=False):
42+
msg = self._messages.get()
43+
44+
if isinstance(msg, StreamClosed):
45+
return None
46+
47+
if msg_obj:
48+
return msg
49+
else:
50+
return msg.data
51+
52+
53+
if __name__ == '__main__':
54+
55+
ws = WebSocketClient('http://localhost:9000/', protocols=['http-only', 'chat'])
56+
ws.connect()
57+
58+
ws.send("Hello world")
59+
print ws.receive()
60+
61+
ws.send("Hello world again")
62+
print ws.receive()
63+
64+
def incoming():
65+
while True:
66+
m = ws.receive()
67+
if m is not None:
68+
print m, len(str(m))
69+
if len(str(m)) == 35:
70+
ws.close()
71+
break
72+
else:
73+
break
74+
print "Connection closed!"
75+
76+
def outgoing():
77+
for i in range(0, 40, 5):
78+
ws.send("*" * i)
79+
80+
# We won't get this back
81+
ws.send("Foobar")
82+
83+
greenlets = [
84+
gevent.spawn(incoming),
85+
gevent.spawn(outgoing),
86+
]
87+
gevent.joinall(greenlets)

ws4py/client/threadedclient.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def _receive(self):
102102
for error in s.errors:
103103
self.close(error.code, error.reason)
104104
s.errors.remove(error)
105-
break
105+
break
106106

107107
elif s.has_message:
108108
self.received_message(s.message)
@@ -121,10 +121,10 @@ def _receive(self):
121121
print "".join(traceback.format_exception(*exc_info()))
122122
finally:
123123
self.close_connection()
124-
if self.stream.closing:
125-
self.closed(self.stream.closing.code, self.stream.closing.reason)
126-
else:
127-
self.closed(1006)
124+
if self.stream.closing:
125+
self.closed(self.stream.closing.code, self.stream.closing.reason)
126+
else:
127+
self.closed(1006)
128128

129129
if __name__ == '__main__':
130130
import time

ws4py/server/geventserver.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,11 @@ def echo_handler(websocket, environ):
8080
try:
8181
while True:
8282
msg = websocket.receive(msg_obj=True)
83-
websocket.send(msg.data, msg.is_binary)
84-
except IOError:
83+
if msg is not None:
84+
websocket.send(msg.data, msg.is_binary)
85+
else:
86+
break
87+
finally:
8588
websocket.close()
8689

8790
server = WebSocketServer(('127.0.0.1', 9000), echo_handler)

ws4py/server/handler/threadedhandler.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ def _receive(self):
183183
self.sock.setblocking(1)
184184
while not self.terminated:
185185
bytes = self.read_from_connection(next_size)
186-
if not bytes and next_size > 0:
187-
break
186+
if not bytes and next_size > 0:
187+
break
188188

189189
with self._lock:
190190
s = self.stream
@@ -203,7 +203,7 @@ def _receive(self):
203203
for error in s.errors:
204204
self.close(error.code, error.reason)
205205
s.errors.remove(error)
206-
break
206+
break
207207

208208
elif s.has_message:
209209
self.received_message(s.message)
@@ -221,12 +221,12 @@ def _receive(self):
221221
except:
222222
print "".join(traceback.format_exception(*exc_info()))
223223
finally:
224-
self.client_terminated = self.server_terminated = True
224+
self.client_terminated = self.server_terminated = True
225225
self.close_connection()
226-
if self.stream.closing:
227-
self.closed(self.stream.closing.code, self.stream.closing.reason)
228-
else:
229-
self.closed(1006)
226+
if self.stream.closing:
227+
self.closed(self.stream.closing.code, self.stream.closing.reason)
228+
else:
229+
self.closed(1006)
230230

231231

232232
class EchoWebSocketHandler(WebSocketHandler):

0 commit comments

Comments
 (0)