2012-03-09 12 views
0

私は、websocketをサポートするPython用の単純なサーバーハンドルを実装する作業に直面しました。もちろん、私はtornadoIOについて知っていますが、問題はそれを実装することです。 接続の手順とハンドシェイク(秘密鍵の交換)はしましたが、問題があります。 1)クライアント(ブラウザ)からのメッセージは来るが、コード化されている。私はそれに関する情報を見つけましたが、それらを解読する方法を理解できませんでした。ドキュメンテーションによれば、メッセージはマスクの下に隠されています(私はそれをXORと理解しています)が、このマスクを開くための鍵はクライアント(ブラウザ)によって見られませんでした。 2)サーバーを送信するメッセージ、クライアント(ブラウザー)は無視されます。ドキュメントwebsocket server on python.problems

conn.send(bytes(0x00)) 
conn.send(u'test'.encode('utf-8')) 
conn.send(bytes(0xFF)) 

アップロードされたソースコードhere に応じて送信すると、私はのWebSocketプロトコルの二つの異なる主要なバリエーションがありますが、ここで

# -*- coding: utf-8 -*- 
from __future__ import unicode_literals 
import socket,sys,hashlib,time 
from base64 import b64encode 
from threading import Thread 
#=================================== 
bindto=['127.3.1.4',80] 
thr_kill=False 

def getsett(text,ss,si,es): 
#this function i'm use for cut strings by known patterns 
    global getsett_i1,getsett_i2 
    if text==None: return None 
    if ss==None: return None 
    if es==None: return None 
    text1=text.lower() 
    ss=ss.lower() 
    es=es.lower() 
    if ss!='': getsett_i1=text1.find(ss,si) 
    else: getsett_i1=si 
    if getsett_i1==-1: return None 
    if es!='': getsett_i2=text1.find(es,getsett_i1+len(ss)) 
    else: getsett_i2=len(text1) 
    if getsett_i2==-1: return None 
    return text[getsett_i1+len(ss):getsett_i2] 

def thr_waitclient(): 
    global bindto,thr_kill 
    serv=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
    serv.bind((bindto[0],bindto[1])) 
    while thr_kill==False: 
     serv.listen(1) 
     conn,adr=serv.accept() 
     data=conn.recv(4096) 
     print data 
#checking connection type 
     if getsett(data,'connection: ',0,"\r\n").lower()=='upgrade' and getsett(data,'upgrade: ',0,"\r\n").lower()=='websocket': 
#handshake 
     wbs=getsett(data,'Sec-WebSocket-Key: ',0,"\r\n") 
     conn.send("HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "+b64encode(hashlib.sha1(wbs+'258EAFA5-E914-47DA-95CA-C5AB0DC85B11').digest())+"\r\nSec-WebSocket-Origin: *\r\nAccess-Control-Allow-Origin: *\r\nOrigin: *\r\nAccess-Control-Allow-Credentials:true\r\nAccess-Control-Allow-Headers:content-type\r\n\r\n") 
#wait for clien's messahe,then send response 
     while True: 
      print conn.recv(4096) #first problem:message is coded 
      conn.send(bytes(0x00)) 
      conn.send(u'test'.encode('utf-8')) 
      conn.send(bytes(0xFF)) 
      #second problem: client ignore message 
      time.sleep(0.5) 
     else: 
     conn.close() 
    serv.close() 

Thread(None,thr_waitclient).start() 
while thr_kill!=True: 
    time.sleep(0.3) 
sys.exit(0) 
+0

あなたは、アウトバーン、ws4py、txwsとして既存の実装で見たことがありますか? – jfs

答えて

2

源を投稿してください。あなたのサンプルコードは、どちらのプロトコルでも動作しない両方の組み合わせです。

最近のバージョンのChrome、Firefox、IE10は、新しいHyBi/IETFプロトコルを使用しています。 Chromeの旧バージョンと現在のバージョンのSafari(デスクトップとモバイル)では古いHixieプロトコルを使用しています。

Hixieプロトコルは、フレームの開始を示す '\ x00'とフレームの終了を示す '\ xff'を使用しました。 Hixieプロトコルは、ブラウザからサーバーへのデータをマスクしませんでした。 Hixieプロトコルには、75と76という2つのメジャーバージョンがあります。バージョン76では、ヘッダーの直後で、通常のフレームの前に交換されるデータが追加されています。

最新のHyBi/IETFプロトコルでは、ペイロードの長さと別の終了マーカーを含まない2〜10バイトのヘッダーが使用されます。より新しいプロトコルでは、ブラウザからサーバへのペイロードデータは、4バイトのXORマスクを使用してマスクされます。ヘッダーの後の最初の4バイトは、ブラウザーからサーバーへのケースのマスクです。サーバからブラウザへのデータはマスクされていません。ハンドシェイクのヘッダーとプロセスは、HyBiプロトコルでも異なります。

多くのWebSocketサーバーは、WebSocketプロトコルのHixieとHyBi/IETFの両方のバージョンをサポートしています(ブラウザが送信したヘッダーから使用しているバージョンを確認できます)。ここで

は、さまざまなプロトコルのバージョンの仕様です:

+0

Thx ** kanaka **! – GenryRar

+0

私は実際にプロトコルのバージョンに間違いがあります。私は右の握手と間違った送受信を使用しています))誰も私にこれを助けることができますか?私は、クライアントにdaaを正しく送信するためのアンマスクとアルゴリズムのアルゴリズムについて言います。私はこれについて十分な知識がないと恐れている:( – GenryRar

+0

Thx again ** kanaka **、私はドキュメントを読み直して、今はすべてうまくいく! – GenryRar