This repository was archived by the owner on Sep 17, 2019. It is now read-only.
forked from Lawouach/WebSocket-for-Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathecho_gevent_server.py
More file actions
180 lines (149 loc) · 5.94 KB
/
Copy pathecho_gevent_server.py
File metadata and controls
180 lines (149 loc) · 5.94 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# -*- coding: utf-8 -*-
from gevent import monkey; monkey.patch_all()
import argparse
import random
import os
import gevent
import gevent.pywsgi
from ws4py.server.geventserver import UpgradableWSGIHandler
from ws4py.server.wsgi.middleware import WebSocketUpgradeMiddleware
from ws4py.websocket import EchoWebSocket
class BroadcastWebSocket(EchoWebSocket):
def received_message(self, m):
# self.clients is set from within the server
# and holds the list of all connected servers
# we can dispatch to
for client in self.clients:
client.send(m)
def closed(self, code, reason="A client left the room without a proper explanation."):
if self in self.clients:
self.clients.remove(self)
try:
for client in self.clients:
client.send(reason)
finally:
self.clients = None
delattr(self, 'clients')
class EchoWebSocketServer(gevent.pywsgi.WSGIServer):
handler_class = UpgradableWSGIHandler
def __init__(self, host, port):
gevent.pywsgi.WSGIServer.__init__(self, (host, port))
self.host = host
self.port = port
self.application = self
# let's use wrap the websocket handler with
# a middleware that'll perform the websocket
# handshake
self.ws = WebSocketUpgradeMiddleware(app=self.ws_app,
websocket_class=BroadcastWebSocket)
# keep track of connected websocket clients
# so that we can brodcasts messages sent by one
# to all of them. Aren't we cool?
self.clients = []
def __call__(self, environ, start_response):
"""
Good ol' WSGI application. This is a simple demo
so I tried to stay away from dependencies.
"""
if environ['PATH_INFO'] == '/favicon.ico':
return self.favicon(environ, start_response)
if environ['PATH_INFO'] == '/ws':
return self.ws(environ, start_response)
if environ['PATH_INFO'].startswith('/js'):
return self.static(environ, start_response)
return self.webapp(environ, start_response)
def ws_app(self, websocket):
websocket.clients = self.clients
self.clients.append(websocket)
g = gevent.spawn(websocket.run)
g.join()
def favicon(self, environ, start_response):
"""
Don't care about favicon, let's send nothing.
"""
status = '200 OK'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)
return ""
def static(self, environ, start_response):
"""
Not the sexiest static handler but does the job
for the demo
"""
path = os.path.normpath(os.path.join(os.path.dirname(__file__),
'./static/%s' % environ['PATH_INFO']))
if not os.path.exists(path):
status = '404 Not Found'
headers = [('Content-type', 'text/plain')]
return ""
status = '200 OK'
headers = [('Content-type', 'text/javascript')]
start_response(status, headers)
return file(path).read()
def webapp(self, environ, start_response):
"""
Our main webapp that'll display the chat form
"""
status = '200 OK'
headers = [('Content-type', 'text/html')]
start_response(status, headers)
return """<html>
<head>
<script type='application/javascript' src='/js/jquery-1.6.2.min.js'></script>
<script type='application/javascript'>
$(document).ready(function() {
websocket = 'ws://%(host)s:%(port)s/ws';
if (window.WebSocket) {
ws = new WebSocket(websocket);
}
else if (window.MozWebSocket) {
ws = MozWebSocket(websocket);
}
else {
console.log('WebSocket Not Supported');
return;
}
window.onbeforeunload = function(e) {
$('#chat').val($('#chat').val() + 'Bye bye...\\n');
ws.close(1000, '%(username)s left the room');
if(!e) e = window.event;
e.stopPropagation();
e.preventDefault();
};
ws.onmessage = function (evt) {
$('#chat').val($('#chat').val() + evt.data + '\\n');
};
ws.onopen = function() {
ws.send("%(username)s entered the room");
};
ws.onclose = function(evt) {
$('#chat').val($('#chat').val() + 'Connection closed by server: ' + evt.code + ' \"' + evt.reason + '\"\\n');
};
$('#send').click(function() {
console.log($('#message').val());
ws.send('%(username)s: ' + $('#message').val());
$('#message').val("");
return false;
});
});
</script>
</head>
<body>
<form action='#' id='chatform' method='get'>
<textarea id='chat' cols='35' rows='10'></textarea>
<br />
<label for='message'>%(username)s: </label><input type='text' id='message' />
<input id='send' type='submit' value='Send' />
</form>
</body>
</html>
""" % {'username': "User%d" % random.randint(0, 100),
'host': self.host,
'port': self.port}
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Echo gevent Server')
parser.add_argument('--host', default='127.0.0.1')
parser.add_argument('-p', '--port', default=9000, type=int)
args = parser.parse_args()
server = EchoWebSocketServer(args.host, args.port)
server.serve_forever()