クイックノート

ちょっとした発見・アイデアから知識の発掘を

pythonでWebSocketサーバーを作ってみる

ユーザーがブラウザで何かアクションを起こした時、
その情報をサーバーがキャッチして、
ユーザーに必要な情報をフィードバックする
なんて事をWebサイトでしようと思うと、
ブラウザとサーバーの双方向通信が必要です。

そんな、双方向通信を実現してくれるのが、
WebSocketです。

ネットで検索すれば、様々な解説記事が見つかりますが、
なんだかサンプルコードが長い。。。

ちょっと試したいだけだから、もっと短いコードで動かないの?という人のために、
この記事では、短いサンプルコードを使ってWebSocketをとりあえず動かしてみます。

また、最低限知っておくべきことと、
必要な準備についてもまとめておきます。

WebSocket とは

WebSocket は、その名の通り、
Web上でソケット通信を行うための API です。

通常、Webページを見る時は、
ブラウザがページをくださいというのと、
サーバーがページを送るという
限定的な通信に限られます。

ところが、ユーザーのアクションに合わせて、
サーバーからもリアクションを返したいとなると、
もっと柔軟な通信ができないと困ります。

そのような自由な双方向通信を実現するのが、
WebSocket になります。

ソケット通信

ソケット通信はコンピューターの通信で最も基本的な通信です。

ソケットは、電球を差し込む穴などを指す言葉として使われますが、
ここでは、通信の出入り口のようなものに対応します。

本当のコンピューターの通信の出入口はLANケーブルをLANポートだったり、
無線LANのアンテナだったりしますが、
ソケットは、プログラム上での通信の出入り口に当たります。

LINEやメールなど、通信を行うアプリケーションはそれぞれソケットを持っていて、
それを、通信相手のソケットに繋ぐことで、通信が行われます。

複数のソケットがあると、どのメッセージをどのソケットに渡すかを振り分ける必要がありますが、
ソケットには、いわゆるポート番号と呼ばれる番号が割り振られているので、
その番号を使って相手のソケットと通信することができます。

WebSocket を使った通信

WebSocketを使うと、どのようにサーバーと繋がるのでしょうか。

まず、Webページをダウンロードするために、
ブラウザはHTTPサーバーに接続してウェブページをもらいます。
この通信もソケットが使われていますが、これはWebSocketではありません。

この時、WebSocketでの通信を行うスクリプトも一緒に受け取り、
その後の通信は、このスクリプト、WebSocketクライアントが、
WebSocketサーバーとの間で行います。

f:id:u874072e:20180601170000p:plain

絵では、HTTPサーバーとWebSocketサーバーあることを分かりやすくするために、
2台のサーバーに分けて書きましたが、サーバー自体は1台で、
そのうえで、HTTPとWebSocketの二つの処理が動いていてもかまいません。

ユーザー側は最初何ももっていないので、
サーバー側が、WebSocketクライアントを内蔵したウェブページと、
WebSocketサーバーを用意しておくことになりますね。

WebSocket のサンプルコード

WebSocketを動かしてみるには、
WebSocketクライアントを記述したスクリプト込みのウェブページファイルと、
Websocketサーバーを作る必要があります。

今回は、簡単な例として、
新しくページにアクセスがあると、
他のユーザーにその通知を行うというサンプルコードを動かしてみましょう。

WebSocketクライアント内臓のウェブページ

ブラウザで表示するhtmlファイルには、
WebSocketクライアントを埋め込んでおく必要があります。

下のコードのスクリプトの部分がそれに当たります。

websoclet_client.html

<html>
<head>
  <script src="http://code.jquery.com/jquery-latest.min.js">
  </script>
  <script>
    $(function(){
      var ws = new WebSocket("ws://localhost:9999/");
      var log = "";
      ws.onmessage = function(message){
        log = log + "<br>" + message.data;
        document.getElementById("txt").innerHTML = log;
      }
    })
  </script>
</head>

<body>
  message: <br>
  <div id = "txt"></div>
</body>

</html>

new WebSocket により、接続先を指定してソケットを生成しますが、
今回は、ローカル上で動かすので、localhostとしています。
実際には、WebSocketサーバーを配置したホスト及びポートを指定します。

そして、メッセージ受信時のイベントハンドラ ws.onmessage に、
メッセージを受信した時の処理を記述します。
今回は、サーバーから受け取ったメッセージの内容"message.data"
を順番に表示するだけです。

WebSocketサーバー

WebSocketのサーバーも準備する必要があります。

WebSocketサーバー自体はどのような言語で記述しても問題ありません。
クライアントと統一したければ javascript を使うのですが、
その場合は、node.js のインストールが必要です。

今回は、コードも簡潔にかける python でサーバーを作ってみました。
パッケージ websocket-serverpip でインストールするだけで、
かなりシンプルに書けてしまいます。

server.py

from websocket_server import WebsocketServer
from datetime import datetime

def new_client(client, server):
    server.send_message_to_all(datetime.now().isoformat() + ": new client joined!")

server = WebsocketServer(9999, host="localhost")
server.set_fn_new_client(new_client)
server.run_forever()

サーバーでは、クライアントからの接続を待ち受けるソケットを、
WebsocketServerで生成しています。
この時、ポートやホストはクライアントで指定しているものと同じものであることに注意しましょう。

server.set_fn_new_clientでクライアントが新たに接続した時のイベントハンドラを設定していて、
その中身は、接続時刻を書いたメッセージを接続中のクライアントすべてに送るというものです。

実行手順

とりあえずの動きを確認するため、サーバーは全てローカルで実行します。

1. WebSocketサーバーを実行する

python server.py

で、WebSocketサーバーを実行し、
クライアントの接続を待ち受けます。

2. HTTPサーバーを実行する

python -m SimpleHTTPServer 8080

を「websoclet_client.html」のあるディレクトリで実行し、
ブラウザのアクセスを待ち受けます。

WebSocketを試したいだけなら、 実は、「websoclet_client.html」をそのまま開くだけでもOKです。

3. ブラウザからウェブページにアクセスする

ブラウザのアドレスバーに

http://localhost:8080/websoclet_client.html

を入力します。

すると、アクセス時刻が表示されるはずです。

そのまま、新しいタブで同じページにアクセスすると面白いことが起こります。
2つ目のタブのアクセス時間が、1つ目のタブにも表示されるのです。

f:id:u874072e:20180601173233p:plainf:id:u874072e:20180601173245p:plain

これで、ブラウザとサーバー間で相互に通信が出来ている様子が確認できますね。

まとめ

WebSocketをとりあえず動かしてみるための簡単なサンプルコードを作ってみました。
削りに削ったので、重要なものも説明から漏れていますが、
流れをつかむにはいいのではないかと思います。

プライバシーポリシー