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
|
#!./uwsgi --http-socket :9090 --http-raw-body --gevent 100 --module tests.websockets_chat_2
import uwsgi
import time
import gevent
from gevent.queue import Queue
class ClientManager(object):
clients = set()
@classmethod
def add(cls, client):
cls.clients.add(client)
@classmethod
def remove(cls, client):
cls.clients.remove(client)
@classmethod
def count(cls):
return len(cls.clients)
@classmethod
def broadcast(cls, data):
data = "{0} {1}".format(time.time(), data)
def do_broadcast():
for c in cls.clients:
c.send(data)
gevent.spawn(do_broadcast)
class Client(object):
def __init__(self):
self.ctx = None
self.send_queue = Queue()
self.jobs = []
def _recv_job(self):
while True:
data = uwsgi.websocket_recv(request_context=self.ctx)
self.on_data(data)
def _send_job(self):
while True:
data = self.send_queue.get()
uwsgi.websocket_send(data, request_context=self.ctx)
def _exit(self, *args):
for j in self.jobs:
j.unlink(self._exit)
gevent.killall(self.jobs)
ClientManager.remove(self)
self.on_exit()
def on_data(self, data):
print "GOT: {0}".format(data)
ClientManager.broadcast(data)
def on_exit(self):
print "bye bye..."
def send(self, data):
self.send_queue.put(data)
def start(self):
uwsgi.websocket_handshake()
self.ctx = uwsgi.request_context()
ClientManager.add(self)
self.jobs.extend([
gevent.spawn(self._recv_job),
gevent.spawn(self._send_job),
])
for j in self.jobs:
j.link(self._exit)
gevent.joinall(self.jobs)
def application(env, sr):
ws_scheme = 'ws'
if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
ws_scheme = 'wss'
if env['PATH_INFO'] == '/':
sr('200 OK', [('Content-Type', 'text/html')])
return """
<html>
<head>
<script language="Javascript">
var s = new WebSocket("%s://%s/foobar/");
s.onopen = function() {
alert("connected !!!");
s.send("ciao");
};
s.onmessage = function(e) {
var bb = document.getElementById('blackboard')
var html = bb.innerHTML;
bb.innerHTML = html + '<br/>' + e.data;
};
s.onerror = function(e) {
alert(e);
}
s.onclose = function(e) {
alert("connection closed");
}
function invia() {
var value = document.getElementById('testo').value;
s.send(value);
}
</script>
</head>
<body>
<h1>WebSocket</h1>
<input type="text" id="testo"/>
<input type="button" value="invia" onClick="invia();"/>
<div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
</div>
</body>
</html>
""" % (ws_scheme, env['HTTP_HOST'])
elif env['PATH_INFO'] == '/favicon.ico':
return ""
elif env['PATH_INFO'] == '/foobar/':
print "websockets..."
client = Client()
client.start()
return ""
|