[Python] communicates with Jsclient via WebSocket

Source: Internet
Author: User
Tags base64 ord sha1

Most sites use HTTP protocol communication. HTTP is a non-connected protocol. The server-side talent sends a corresponding response only when the client is requested. the HTTP Request package is also larger, assuming only very small data traffic. Too much overhead. As a result, we are able to use the websocket Protocol to implement connection-oriented communication with minimal overhead.

Detailed websocket Introduction visible http://zh.wikipedia.org/wiki/WebSocket

Here, we describe how to use Python to communicate with the front-end js .

WebSocket After the handshake is completed using the HTTP protocol, WebSocket communication is not made directly through http .

So, use websocket Roughly two steps: Use HTTP handshake, communication.

JS processing websocket to use the ws module;Python processing uses the socket Module Setup TCP connection can be, than the general Socket , just one more handshake and the steps of data processing.

Shake hands
Process

Package format

The JS client first sends a handshake packetto the server-side python in the following format:

Get/chat Http/1.1host:server.example.comupgrade:websocketconnection:upgradesec-websocket-key: Dghlihnhbxbszsbub25jzq==origin:http://example.comsec-websocket-protocol:chat, Superchatsec-websocket-version:13

Server Response Package Format:

http/1.1 101 Switching protocolsupgrade:websocketconnection:upgradesec-websocket-accept:s3pplmbitxaq9kygzzhzrbk+ Xoo=sec-websocket-protocol:chat

Thesec-websocket-key is random, and the server constructs a SHA-1 Information Digest with this data.

The methods are:key+migic,SHA-1 encryption,base-64 encryption, such as the following:

processing code in Python

magic_string = ' 258eafa5-e914-47da-95ca-c5ab0dc85b11 ' Res_key = Base64.b64encode (HASHLIB.SHA1 (Sec_key + MAGIC_STRING) . Digest ())

Handshake Complete Code

JS End

JS has a class to handle the WebSocket, after the initialization of their own initiative to send the handshake package. For example, the following:

Python Side

Python accepts the handshake string with the socket, sends it after processing

HOST = ' localhost ' PORT = 3368magic_string = ' 258eafa5-e914-47da-95ca-c5ab0dc85b11 ' handshake_string = ' http/1.1 101                    Switching protocols\r\n "" upgrade:websocket\r\n "" connection:upgrade\r\n " "Sec-websocket-accept: {1}\r\n" "websocket-location:ws://{2}/chat\r\n" "W ebsocket-protocol:chat\r\n\r\n "def handshake (Con): #con为用socket, accept () The socket# obtained here omit the listener. Accept code, detail visible blog:http://blog.csdn.net/ice110956/article/details/29830627 headers = {} shake = Con.recv (1024x768) I F not Len (Shake): Return False header, data = Shake.split (' \r\n\r\n ', 1) for line in Header.split (' \ r \ n ') [1:  ]: Key, val = Line.split (': ', 1) headers[key] = val if ' Sec-websocket-key ' not in Headers:print        (' This socket was not websocket, client close. ') Con.close () return False Sec_key = headers[' Sec-websocket-key '] Res_key = Base64.b64encode (HASHLIB.SHA1 (sec_ Key + MAgic_string). Digest ()) Str_handshake = Handshake_string.replace (' {1} ', Res_key). Replace (' {2} ', HOST + ': ' + str (PORT)) Print Str_handshake con.send (str_handshake) return True

Communication

Different versions of the browser-defined data frame format,Python to send and receive when it is processed to get the matching format of the packet, the ability to communicate.

PythonReceive

Python receives the data sent from the browser. To analyze the ability to get the practical data.

Browser package format

Fixed bytes:

(0001 or 0002) is useless here, ignore

Packet length byte:

The first bit is definitely 1. Ignore. The remaining 7 bits are able to get an integer (0 ~ 127), in which

(1-125) Table This byte is a length byte. The size is the length;

(126) The next two bytes of the table is the length;

(127) The next eight bytes of the table is the length;

In this way, the length of the data is expressed and the data bits are saved.

Mark Mask:

The Mark mask is 4 bytes after Kanenaga , and then the sibling data is to be calculated with the Mark mask to get real data.

Brother Data:

The way to get real data: To do an XOR operation for each xof the sibling data, and the first i%4 bit of the mask , where i is The index of x in the sibling data.

Full code

def recv_data (self, num):    try:        all_data = self.con.recv (num)        if not Len (all_data):            return False    Except:        return False    else:        Code_len = Ord (all_data[1)) & 127        If Code_len = = 126:            masks = All_ DATA[4:8]            data = all_data[8:]        elif Code_len = = 127:            masks = all_data[10:14]            data = all_data[14:]< C14/>else:            masks = all_data[2:6]            data = all_data[6:]        raw_str = ""        i = 0 for        d in data:            raw_ str = Chr (ord (d) ^ ord (masks[i% 4]))            i + = 1        return raw_str

the ws object on the JS side, which can be sent via ws.send (str)

Ws.send (str)

PythonSend

Python needs to be processed to send packets of data. Send package formats such as the following

Fixed byte: fixed 0001 ('\x81)

Kanenaga: Depending on whether thesent data length exceeds0xFFFF (65535) to generate 1 or 3 or 9 bytes to represent the length of the data.

def send_data (self, data):    If data:        data = str (data)    else:        return False    token = "\x81"    length = Len (data)    if length < 126:        token + = Struct.pack ("B", length)    elif length <= 0xFFFF:        token + = struct . Pack ("! BH ", 126, length)    else:        token + = Struct.pack ("! BQ ", 127, length)    #struct为Python中处理二进制数的模块, the binary stream is C. Or the form of a network stream.

data = '%s%s '% (token, data) self.con.send (data) return True

JS End accepts data via callback function ws.onmessage ()

Ws.onmessage = function (result,ntime) {alert ("Data received from the server:"), alert ("The most recent time the data has been sent to now receive a total of use times:" + ntime); Console.log (Result );}

Finally code
Python Service side

# _*_ Coding:utf-8 _*___author__ = ' Patrick ' import socketimport threadingimport sysimport osimport mysqldbimport base64i mport hashlibimport struct # ====== config ======host = ' localhost ' PORT = 3368magic_string = ' 258eafa5-e914-47da-95ca-c5ab                    0dc85b11 ' handshake_string = "http/1.1 101 switching protocols\r\n" "upgrade:websocket\r\n" "Connection:upgrade\r\n" "Sec-websocket-accept: {1}\r\n" "websocket-location : ws://{2}/chat\r\n "" Websocket-protocol:chat\r\n\r\n "Class Th (threading. Thread): Def __init__ (self, Connection,): Threading. Thread.__init__ (self) Self.con = connection def run (self): while True:try:pas  S Self.con.close () def recv_data (self, num): Try:all_data = SELF.CON.RECV (num) if Not Len (All_data): return false Except:return false Else:coDe_len = Ord (all_data[1]) & 127 if Code_len = = 126:masks = all_data[4:8] Dat A = all_data[8:] elif Code_len = = 127:masks = all_data[10:14] data = all_data[14            :] Else:masks = all_data[2:6] data = all_data[6:] raw_str = ""            i = 0 for D in Data:raw_str + = Chr (ord (d) ^ ord (masks[i% 4))) i + = 1 Return RAW_STR # Send data def send_data (self, data): If Data:data = str (data) Else : return False token = "\x81" length = Len (data) if length < 126:token + = s Truct.pack ("B", length) elif length <= 0xffff:token + = Struct.pack ("! BH ", 126, length) Else:token + = Struct.pack ("! BQ ", 127, length) #struct为Python中处理二进制数的模块, the binary stream is C, or the form of a network stream.

data = '%s%s '% (token, data) self.con.send (data) return True # handshake def handshake (Con) : headers = {} shake = Con.recv (1024x768) if not Len (Shake): Return False header, dat A = Shake.split (' \r\n\r\n ', 1) for line in Header.split (' \ r \ n ') [1:]: Key, val = Line.split (': ', 1) Headers[key] = val if ' Sec-websocket-key ' not in the headers:print (' This socket was not WebSocket, Client close. ') Con.close () return False Sec_key = headers[' Sec-websocket-key '] Res_key = Base64.b64encode (HASHL IB.SHA1 (Sec_key + magic_string). Digest ()) Str_handshake = Handshake_string.replace (' {1} ', Res_key). Replace (' {2} ', HOST + ': ' + str (PORT)) print Str_handshake con.send (str_handshake) return True def new_service (): "" "Start a service socket and listen when COMs a connection, start a new thread to handle it" "sock = Socket.sOcket (socket.af_inet, socket. Sock_stream) try:sock.bind ((' localhost ', 3368)) Sock.listen (3368) #链接队列大小 print "Bind Except:print ("Server is already Running,quit") Sys.exit () while True:connecti On, address = Sock.accept () #返回元组 (Socket,add), the accept call enters the Waite status print "Got connection from", address If handshake (connection): print "handshake success" Try:t = Th (connection, layout ) T.start () print ' new thread for client ... ' except:print ' Start New thread error ' connection.close () if __name__ = = ' __main__ ': New_service ()

JS CustomerEnd

<script>var socket = new WebSocket (' ws://localhost:3368 '); ws.onmessage = function (result,ntime) {alert (" Data received from the server: "); alert (" Send data to now receive a total of time: "+ ntime); Console.log (result); </script>

RecommendedBlog

http://blog.csdn.net/fenglibing/article/details/7108982

http://blog.mycolorway.com/2011/11/22/a-minimal-python-websocket-server/

[Python] communicates with Jsclient via WebSocket

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.