Flast-Sockets + redis-py で簡単 Websocket サーバー実装

Python
スポンサーリンク

参考にしたサイト


使うもの


したかったこと

Python とJavascript とのリアルタイム通信

Python 側

  • Flask-Sockets で Websocket サーバーを立てる
  • バックグラウンドでの情報の通信は redis-py を使って行う。

Javascript側

実装

server.py

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2017 zenbook <zenbook@zenbook-XPS>
#
# Distributed under terms of the MIT license.

"""

"""

from flask import Flask
from flask_sockets import Sockets
import redis
import threading
import gevent

app = Flask(__name__)
sockets = Sockets(app)

client = redis.StrictRedis(host='localhost', port=6379, db=0)

class MessageServer(object):
    """Interface for registering and updating WebSocket clients."""

    def __init__(self):
        self.clients = list()
        self.pubsub = client.pubsub()
        self.pubsub.subscribe("channel")

    def __iter_data(self):
        for message in self.pubsub.listen():
            data = message.get('data')
            if message['type'] == 'message':
                app.logger.info(u'Sending message: {}'.format(data))
                yield data

    def register(self, client):
        """Register a WebSocket connection for Redis updates."""
        self.clients.append(client)

    def send(self, client, data):
        """Send given data to the registered client.
        Automatically discards invalid connections."""
        try:
            client.send(data)
        except Exception:
            self.clients.remove(client)

    def run(self):
        """Listens for new messages in Redis, and sends them to clients."""
        for data in self.__iter_data():
            for client in self.clients:
                self.send(client, data)

    def start(self):
        """Maintains Redis subscription in the background."""
        self.run()

ms = MessageServer()

@sockets.route('/mychannel')
def echo_socket(ws):
    ms.register(ws)
    while not ws.closed:
        gevent.sleep(0.1)

@app.route('/')
def hello():
    return 'Hello World!'

if __name__ == "__main__":
    from gevent import pywsgi
    from geventwebsocket.handler import WebSocketHandler
    t = threading.Thread(target=ms.start)
    t.daemon = True
    t.start()
    #ms.start()
    print "WSGI Server starts"
    server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
    server.serve_forever()

ticker.py

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2017 zenbook <zenbook@zenbook-XPS>
#
# Distributed under terms of the MIT license.

"""

"""
from flask import Flask
from flask_sockets import Sockets
import redis
import random
import time

if __name__ == '__main__':
    app = Flask(__name__)
    sockets = Sockets(app)

    client = redis.StrictRedis(host='localhost', port=6379, db=0)
    pubsub = client.pubsub()
    pubsub.subscribe("channel")
    price = 0
    while True:
        price += random.uniform(-10, 10)
        print("Sending Price", price)
        client.publish("channel", price)
        time.sleep(1)

javascript

webSocket = new WebSocket(uri);
webSocket.onopen = function (e) {
    console.log(e.data);
};
webSocket.onopen = function () {
    console.log("OnOpen");
};
webSocket.onerror = function (error) {
  console.log('WebSocket Error ' + error);
};
console.log(webSocket.extensions);

コメント

タイトルとURLをコピーしました