1. What is websocket?
API
Websocket API is the asynchronous communication method of the Next Generation client-server. This communication replaces a single TCP socket. It uses ws or WSS protocol and can be used for any client or server program. Websocket is currently standardized by W3C. Websocket has been received by Firefox
4. Support for browsers such as chrome 4, opera 10.70, and Safari 5.
The greatest advantage of websocket APIS is that servers and clients can push information to each other at any time within a given time range. Websocket is not limited to Ajax (or xhr) communication. Because Ajax requires the client to initiate a request, the websocket server and client can push information to each other. xhr is restricted by the domain, websocket allows cross-origin communication.
Ii. websocket Protocol The websocket protocol is very simple. Here I divide it into clients and servers. On the client side, a new websocket object can be instantiated, but its parameters are slightly different. The parameter format is WS: // yourdomain: Port/path.
The websocket object will automatically parse this string and send it to the specified server port. The first step is to execute handshake. The format of the data sent by the client is similar to this:
GET /chat HTTP/1.1Upgrade: WebSocketConnection: UpgradeHost: www.zendstudio.net:9108Origin: http://www.zendstudio.netCookie: somenterCookie
This is very similar to HTTP header information, and each line ends with "\ r \ n". The above format does not need to be constructed, and the websocket object will be automatically sent, this is transparent to the client. In this case, the server should return the following information:
HTTP/1.1 101 Web Socket Protocol HandshakeUpgrade: WebSocketConnection: UpgradeWebSocket-Origin: http://www.zendstudio.netWebSocket-Location: ws://www.zendstudio.net:9108/chat
From this we can easily see that the handshake part of the websocket protocol is basically an http-like protocol. What's different is that each HTTP request will have such header information interaction, this may have to look terrible in some cases. Websocket only executes this process once, and the subsequent transmission information becomes very concise.
Handshake protocol: The request contains three random key values, two headers, and eight-byte key3 in the body (the text in the brackets is a prompt, there is also a colon between characters that is added to make it seem clear, but there is no real transfer), in order to send a challenge to the server, the server needs to calculate a token based on the three keys, send the request back to the client in the response to prove that you have properly interpreted the request. The calculation method is as follows: For key1, extract the numeric characters to form an integer num, divide it by its own space number spaces, and retain the integer part I1;
Key2 is processed as a method to obtain I2, connect I1 and I2 in the big-Endian character order, and then connect with key3 to obtain an initial sequence, calculate a 16-byte digest using MD5 for this sequence, which is the required token. In addition, it is worth noting that the origin header means that websocket supports cross origin.
3. Client client. html
<HTML>
Iv. server. py
import socketimport structimport hashlibimport threading,randomconnectionlist = {}def sendMessage(message): global connectionlist for connection in connectionlist.values(): connection.send("\x00%s\xFF" %message)def deleteconnection(item): global connectionlist del connectionlist['connection'+item]class WebSocket(threading.Thread): def __init__(self, conn, index, name, remote, path="/"): threading.Thread.__init__(self) self.conn = conn self.index = index self.name = name self.remote = remote self.path = path self.buffer = "" def run(self): 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 += 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) print headers key1 = headers["Sec-WebSocket-Key1"] key2 = headers["Sec-WebSocket-Key2"] if len(data) < 8: data += self.conn.recv(8-len(data)) key3 = data[:8] self.buffer = data[8:] token = self.generate_token(key1, key2, key3) handshake = '\HTTP/1.1 101 Web Socket Protocol Handshake\r\n\Upgrade: WebSocket\r\n\Connection: Upgrade\r\n\Sec-WebSocket-Origin: %s\r\n\Sec-WebSocket-Location: %s\r\n\r\n\' %(headers['Origin'], headers['Location']) self.conn.send(handshake + token) self.handshaken = True print 'Socket %s Handshaken with %s success!' %(self.index, self.remote) sendMessage('Welcome, ' + self.name + ' !') else: self.buffer += self.conn.recv(64) if self.buffer.find("\xFF") != -1: s = self.buffer.split("\xFF")[0][1:] if s == 'quit': print 'Socket %s Logout !' %(self.index) sendMessage(self.name + ' Logout') deleteconnection(str(self.index)) self.conn.close() break else: print 'Socket %s Got msg: %s from %s!' %(self.index,s,self.remote) sendMessage(self.name + ':' + s) self.buffer = "" def generate_token(self, key1, key2, key3): num1=int("".join([digit for digit in list(key1) if digit.isdigit()])) spaces1 = len([char for char in list(key1) if char == " "]) num2 = int("".join([digit for digit in list(key2) if digit.isdigit()])) spaces2 = len([char for char in list(key2) if char == " "]) combined = struct.pack(">II", num1/spaces1, num2/spaces2) + key3 return hashlib.md5(combined).digest()class WebSocketServer(object): def __init__(self): self.socket = None def begin(self): print "WebSocketSerber Start!" self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.bind(("10.3.18.105", 19887)) 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() conectionlist['connection'+str(i)] = connection i = i + 1if __name__ == "__main__": server = WebSocketServer() server.begin()