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
|
# -*- 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 WebSocketWSGIApplication, \
WebSocketWSGIHandler, WSGIServer
from ws4py.websocket import EchoWebSocket
class BroadcastWebSocket(EchoWebSocket):
def opened(self):
app = self.environ['ws4py.app']
app.clients.append(self)
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
app = self.environ['ws4py.app']
for client in app.clients:
client.send(m)
def closed(self, code, reason="A client left the room without a proper explanation."):
app = self.environ.pop('ws4py.app')
if self in app.clients:
app.clients.remove(self)
for client in app.clients:
try:
client.send(reason)
except:
pass
class EchoWebSocketApplication(object):
def __init__(self, host, port):
self.host = host
self.port = port
self.ws = WebSocketWSGIApplication(handler_cls=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':
environ['ws4py.app'] = self
return self.ws(environ, start_response)
return self.webapp(environ, start_response)
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 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='https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.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__':
from ws4py import configure_logger
configure_logger()
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 = WSGIServer((args.host, args.port), EchoWebSocketApplication(args.host, args.port))
server.serve_forever()
|