1. 程式人生 > >websocket實現簡單的通信

websocket實現簡單的通信

clas continue app 線程 for 函數 ets catch solid

websocket server端

#coding=utf8  
#!/usr/bin/python  
  
  
import struct,socket  
import hashlib  
import threading,random  
import time  
import struct  
from base64 import b64encode, b64decode  
  
  
connectionlist = {}  
g_code_length = 0  
g_header_length = 0  
  
  
def hex2dec(string_num):  
    return str(int(string_num.upper(), 16))  
  
  
  
  
def get_datalength(msg):  
    global g_code_length  
    global g_header_length      
      
    print (len(msg))  
    g_code_length = ord(msg[1]) & 127  
    received_length = 0;  
    if g_code_length == 126:  
        #g_code_length = msg[2:4]  
        #g_code_length = (ord(msg[2])<<8) + (ord(msg[3]))  
        g_code_length = struct.unpack(‘>H‘, str(msg[2:4]))[0]  
        g_header_length = 8  
    elif g_code_length == 127:  
        #g_code_length = msg[2:10]  
        g_code_length = struct.unpack(‘>Q‘, str(msg[2:10]))[0]  
        g_header_length = 14  
    else:  
        g_header_length = 6  
    g_code_length = int(g_code_length)  
    return g_code_length  
          
def parse_data(msg):  
    global g_code_length  
    g_code_length = ord(msg[1]) & 127  
    received_length = 0;  
    if g_code_length == 126:  
        g_code_length = struct.unpack(‘>H‘, str(msg[2:4]))[0]  
        masks = msg[4:8]  
        data = msg[8:]  
    elif g_code_length == 127:  
        g_code_length = struct.unpack(‘>Q‘, str(msg[2:10]))[0]  
        masks = msg[10:14]  
        data = msg[14:]  
    else:  
        masks = msg[2:6]  
        data = msg[6:]  
  
  
    i = 0  
    raw_str = ‘‘  
  
  
    for d in data:  
        raw_str += chr(ord(d) ^ ord(masks[i%4]))  
        i += 1  
  
  
    print (u"總長度是:%d" % int(g_code_length))      
    return raw_str    
  
  
def sendMessage(message):  
    global connectionlist  
      
    message_utf_8 = message.encode(‘utf-8‘)  
    for connection in connectionlist.values():  
        back_str = []  
        back_str.append(‘\x81‘)  
        data_length = len(message_utf_8)  
  
  
        if data_length <= 125:  
            back_str.append(chr(data_length))  
        elif data_length <= 65535 :  
            back_str.append(struct.pack(‘b‘, 126))  
            back_str.append(struct.pack(‘>h‘, data_length))  
            #back_str.append(chr(data_length >> 8))  
            #back_str.append(chr(data_length & 0xFF))  
            #a = struct.pack(‘>h‘, data_length)  
            #b = chr(data_length >> 8)  
            #c = chr(data_length & 0xFF)  
        elif data_length <= (2^64-1):  
            #back_str.append(chr(127))  
            back_str.append(struct.pack(‘b‘, 127))  
            back_str.append(struct.pack(‘>q‘, data_length))  
            #back_str.append(chr(data_length >> 8))  
            #back_str.append(chr(data_length & 0xFF))        
        else :  
                print (u‘太長了‘)          
        msg = ‘‘  
        for c in back_str:  
            msg += c;  
        back_str = str(msg)   + message_utf_8#.encode(‘utf-8‘)      
        #connection.send(str.encode(str(u"\x00%s\xFF\n\n" % message))) #這個是舊版  
        #print (u‘send message:‘ +  message)  
        if back_str != None and len(back_str) > 0:  
            print (back_str)  
            connection.send(back_str)  
  
  
def deleteconnection(item):  
    global connectionlist  
    del connectionlist[‘connection‘+item]  
  
  
class WebSocket(threading.Thread):#繼承Thread  
  
  
    GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"  
  
  
    def __init__(self,conn,index,name,remote, path="/"):  
        threading.Thread.__init__(self)#初始化父類Thread  
        self.conn = conn  
        self.index = index  
        self.name = name  
        self.remote = remote  
        self.path = path  
        self.buffer = ""  
        self.buffer_utf8 = ""  
        self.length_buffer = 0  
    def run(self):#重載Thread的run  
        print(‘Socket%s Start!‘ % self.index)  
        headers = {}  
        self.handshaken = False  
  
  
        while True:  
            if self.handshaken == False:  
                print (‘Socket%s Start Handshaken with %s!‘ % (self.index,self.remote))  
                self.buffer += bytes.decode(self.conn.recv(1024))  
  
  
                if self.buffer.find(‘\r\n\r\n‘) != -1:  
                    header, data = self.buffer.split(‘\r\n\r\n‘, 1)  
                    for line in header.split("\r\n")[1:]:  
                        key, value = line.split(": ", 1)  
                        headers[key] = value  
  
  
                    headers["Location"] = ("ws://%s%s" %(headers["Host"], self.path))  
                    key = headers[‘Sec-WebSocket-Key‘]  
                    token = b64encode(hashlib.sha1(str.encode(str(key + self.GUID))).digest())  
  
  
                    handshake="HTTP/1.1 101 Switching Protocols\r\n"                        "Upgrade: websocket\r\n"                        "Connection: Upgrade\r\n"                        "Sec-WebSocket-Accept: "+bytes.decode(token)+"\r\n"                        "WebSocket-Origin: "+str(headers["Origin"])+"\r\n"                        "WebSocket-Location: "+str(headers["Location"])+"\r\n\r\n"  
  
  
                    self.conn.send(str.encode(str(handshake)))  
                    self.handshaken = True    
                    print (‘Socket %s Handshaken with %s success!‘ %(self.index, self.remote))    
                    sendMessage(u‘Welcome, ‘ + self.name + ‘ !‘)    
                    self.buffer_utf8 = ""  
                    g_code_length = 0                      
  
  
            else:  
                global g_code_length  
                global g_header_length  
                mm=self.conn.recv(128)  
                if len(mm) <= 0:  
                    continue  
                if g_code_length == 0:  
                    get_datalength(mm)  
                #接受的長度  
                self.length_buffer = self.length_buffer + len(mm)  
                self.buffer = self.buffer + mm  
                if self.length_buffer - g_header_length < g_code_length :  
                    continue  
                else :  
                    self.buffer_utf8 = parse_data(self.buffer) #utf8                  
                    msg_unicode = str(self.buffer_utf8).decode(‘utf-8‘, ‘ignore‘) #unicode  
                    if msg_unicode==‘quit‘:  
                        print (u‘Socket%s Logout!‘ % (self.index))  
                        nowTime = time.strftime(‘%H:%M:%S‘,time.localtime(time.time()))  
                        sendMessage(u‘%s %s say: %s‘ % (nowTime, self.remote, self.name+‘ Logout‘))                        
                        deleteconnection(str(self.index))  
                        self.conn.close()  
                        break #退出線程  
                    else:  
                        #print (u‘Socket%s Got msg:%s from %s!‘ % (self.index, msg_unicode, self.remote))  
                        nowTime = time.strftime(u‘%H:%M:%S‘,time.localtime(time.time()))  
                        sendMessage(u‘%s %s say: %s‘ % (nowTime, self.remote, msg_unicode))    
                    #重置buffer和bufferlength  
                    self.buffer_utf8 = ""  
                    self.buffer = ""  
                    g_code_length = 0  
                    self.length_buffer = 0  
            self.buffer = ""  
  
  
class WebSocketServer(object):  
    def __init__(self):  
        self.socket = None  
    def begin(self):  
        print( ‘WebSocketServer Start!‘)  
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
        self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  
        self.socket.bind(("0.0.0.0",12345))  
        self.socket.listen(50)  
  
  
        global connectionlist  
  
  
        i=0  
        while True:  
            connection, address = self.socket.accept()  
  
  
            username=address[0]       
            newSocket = WebSocket(connection,i,username,address)  
            newSocket.start() #開始線程,執行run函數  
            connectionlist[‘connection‘+str(i)]=connection  
            i = i + 1  
  
  
if __name__ == "__main__":  
    server = WebSocketServer()  
    server.begin() 

  

websocket client 瀏覽器

<!DOCTYPE html>
<html>  
<head>  
    <title>WebSocket</title>  
  
    <style>  
        html, body {  
            font: normal 0.9em arial, helvetica;  
        }  
  
        #log {  
            width: 440px;  
            height: 200px;  
            border: 1px solid #7F9DB9;  
            overflow: auto;  
        }  
  
        #msg {  
            width: 330px;  
        }  
    </style>  
  
    <script>  
        var socket;  
  
        function init() {  
            var host = "ws://127.0.0.1:12345/";
            try {  
                socket = new WebSocket(host);  
                socket.onopen = function (msg) {  
                    log(‘Connected‘);  
                };  
                socket.onmessage = function (msg) {  
                    log(msg.data);  
                };  
                socket.onclose = function (msg) {  
                    log("Lose Connection!");  
                };  
            }  
            catch (ex) {  
                log(ex);  
            }  
            $("msg").focus();  
        }  
  
        function send() {  
            var txt, msg;  
            txt = $("msg");  
            msg = txt.value;  
            if (!msg) {  
                alert("Message can not be empty");  
                return;  
            }  
            txt.value = "";  
            txt.focus();  
            try {  
                socket.send(msg);  
            } catch (ex) {  
                log(ex);  
            }  
        }  
  
        window.onbeforeunload = function () {  
            try {  
                socket.send(‘quit‘);  
                socket.close();  
                socket = null;  
            }  
            catch (ex) {  
                log(ex);  
            }  
        };  
  
  
        function $(id) {  
            return document.getElementById(id);  
        }  
        function log(msg) {  
            $("log").innerHTML += "<br>" + msg;  
        }  
        function onkey(event) {  
            if (event.keyCode == 13) {  
                send();  
            }  
        }  
    </script>  
  
</head>  
  
  
<body onload="init()">  
<h3>WebSocket</h3>  
<br><br>  
  
<div id="log"></div>  
<input id="msg" type="textbox" onkeypress="onkey(event)"/>  
<button onclick="send()">發送</button>  
</body>  
  
</html>  

  

websocket實現簡單的通信