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