Search on the blog

2016年8月12日金曜日

TornadoでWebSocketを使ってみた

WebSocketとは?
ウェブサーバとウェブブラウザ間で双方向通信を行うための規格。
WebSocketを使うことで、サーバ側からクライアント側にプッシュ配信を行うことができる。通信ごとにコネクションを張り替えるのではなく、すべての通信を一つのコネクションで行うことができる。

Tornadoとは?
PythonのWebフレームワーク/非同期通信のライブラリ。
数万単位のコネクションにスケールすることができ、WebSocketのようにユーザごとに長期のコネクションを構築しておきたい場合に有用。

サンプル
チャットアプリを作ってみた。

サーバ側のコード。
tornado.websocket.WebSocketHandlerクラスを継承して、必要なイベントハンドラメソッドをオーバーライドすればよい。

import tornado.ioloop
import tornado.web
import tornado.websocket

class ChatHandler(tornado.websocket.WebSocketHandler):
 clients = []

 def open(self):
  if self not in ChatHandler.clients:
   ChatHandler.clients.append(self)

 def on_message(self, message):
  for c in ChatHandler.clients:
   c.write_message(message)

 def on_close(self):
  if self in ChatHandler.clients:
   ChatHandler.clients.remove(self)

class MainHandler(tornado.web.RequestHandler):
 def get(self):
  self.render('main.html')

if __name__ == "__main__":
 application = tornado.web.Application([
  (r"/chat/main.html", MainHandler),
  (r"/chat/websocket", ChatHandler),
 ])
 application.listen(8888)
 tornado.ioloop.IOLoop.current().start()

クライアント側のコード。WebSocketクラスを使って接続、メッセージ送信、メッセージ受信時の処理を行う。
<!DOCTYPE html>
<html>
  <head>
    <title>websocket chat</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
    <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    <script>
      $(function() {
        socket = new WebSocket("ws://kenjih.com:8888/chat/websocket");
        socket.onopen = function() {};
        socket.onmessage = function(e) {
          $("#msgbox").append($('<p>'+e.data+'</p>'));
        };
        $('#send').click(function(){
          socket.send($('#msg').val());
          $('#msg').val('');
        });
        $('#msg').keydown(function(e) {
          if (e.keyCode == 13) {
            socket.send($('#msg').val());
            $('#msg').val('');
          }
        });
      });
    </script>
  </head>
  <body>
    <div class="container">
      <div class="row">
      <h1>Websocket Chat Room</h1>
      </div>
      <div class="row">
        <div class="col-xs-5">
          <div class="input-group">
            <input id="msg" type="text" class="form-control" placeholder="put your message...">
            <span class="input-group-btn">
              <button id="send" class="btn btn-primary" type="button">Send</button>
            </span>
          </div>
        </div>
        <div class="col-xs-7">
          <div class="panel panel-primary">
            <div class="panel-heading">
              <h3 class="panel-title">Messages</h3>
            </div>
            <div id="msgbox" class="panel-body"></div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

0 件のコメント:

コメントを投稿