ページ

2011年1月6日

Python用のWebSocketのクライアント作った

数日前にpypiには登録していたのですが、もうちょっと機能を追加してPython用のWebSocketのクライアントを作りました。githubにいます。pypiはこっち。pip install websocket-clientでインストールできます。プロトコルが変わるとかいろいろありそうですが、まあ、WebSocketはいろいろ変遷してきたので、今更驚かされません。

作った理由は、うーん、何でしょう?何となく書いてみました、という感じです。WebSocketのサーバのテストとか、Pythonのアプリで接続を維持したまま、Webサーバとお話するとか・・・。この前作った、WebSocketのデータを複数サーバでリレーさせるときの通信手段とか・・・。Webサーバでクライアント・サーバのころのような通信ができるようになるというのは、ブラウザを抜きにしてもすごいことだと思うんですね。

今、サポートしているのは、hybi00(hixie76)です。ちょっと古い実装だとhixie75しかサポートしていないサーバもいるらしいので、そういう人はばっさり捨てましょう。hybi00はSafariの今の最新版、iOS4.2のMobileSafari、Chromeがサポートしています。

使い方は、githubのページを見てください。まあ、こんな感じ

from websocket import create_connection
ws = create_connection("ws://localhost:5000/echo")
print "Sending 'Hello, World'..."
ws.send("Hello, World")
print "Sent"
print "Reeiving..."
result =  ws.recv()
print "Received '%s'" % result
ws.close()

基本的にsocketモジュールっぽくしようとして、その後、妥協しています。websocketのオブジェクトを作って、あとは、socketのようにsend/recvをやります。
で、それから、JavaScriptのWebSocketのようにコールバックベースでも書けます。
import websocket
import thread
import time

def on_message(ws, message):
    print message

def on_error(ws, error):
    print error

def on_close(ws):
    print "### closed ###"

def on_open(ws):
    def run(*args):
        for i in range(3):
            time.sleep(1)
            ws.send("Hello %d" % i)
        time.sleep(1)
        ws.close()
        print "thread terminating..."
    thread.start_new_thread(run, ())


if __name__ == "__main__":
    websocket.enableTrace(True)
    ws = websocket.WebSocketApp("ws://localhost:5000/chat",
                                on_message = on_message,
                                on_error = on_error,
                                on_close = on_close)
    ws.on_open = on_open
    
    ws.run_forever()

どっちかいいかはよくわかりません。ちなみに、僕はgeventでmonkey patchをあてて強調スレッドで動かしてます。最初は久しぶりにTwistedを使おうかと思ったのですが、やめました。
それから、英語のドキュメントを読みながら書いたので、読み間違えているところがあったらごめんなさい。まあ、日本語でも読み間違えることはあるので、ごめんなさい。

実装してみて、やっぱりWebSocketのHandshakeでkeyを3つも作って、サーバのレスポンスが問題ないかバリデーションする意味がさっぱり分からない。
WebSocketのハンドシェークでキーを3つ作って、一回のGETでサーバに送ります。キーを受け取ったサーバは、その3つのキーからmd5のハッシュ値を計算してクライアント返します。クライアントは、送ったキーのmd5のハッシュ値とサーバから受け取ったハッシュ値が同じ値かどうかチェックします。それだけです。ハッシュ値はちょっとめんどいけど、キーから計算できるものです。ハッシュ値を使うところはそこだけなので、何をやりたいのかさっぱり分かりません。sec-webscoket-xxxのsecってsecureだと思うんだけど、何もsecureじゃないです。
その後のデータの送受信も暗号化されるわけではないので、めんどーな処理という以外にメリットが感じられません。うーん、これの計算でクライアントを作る気が一瞬なくなったので、そういうメリットはあるかな?

でわでわ。

0 件のコメント: