# # websocket.py
Import socket import struct import hashlib,base64 import threading,random #线程, sockets, hash table, random number #存放链接客户fd, tuple connectionlist = { #发送指定的消息 def sendmessage (message): #对全局变量的引用 global connectionlist #向客户端集合中每个成员发送消息 #%: String compositing #,: string overlay for Conne Ction in Connectionlist.values (): Connection.send ("\x00%s\xff"%) #删除连接, delete Connection object item from collection (Make a connection append to connection) def Delet Econnection (item): Global connectionlist del connectionlist[' connection ' +item] #定义WebSocket对象 (thread-based object) class WebSocket (Threading. Thread): # def __init__ (Self,conn,index,name,remote, path= "/"): #初始化线程 Threading. Thread.__init__ (self) #初始化数据, all stored in its own data structure self SELF.CONN = conn Self.index = Index Self.name = name Self.remote = Remote Self.path = Path Self.buffer = "" #运行线程 def Run (self): #Log输出, Socket index startup print ' socket%s start! '% SE
Lf.index headers = {} #Socket是否握手的标志, initialized to false. Self.handshaken = False #循环执行如下逻辑 while True: #如果没有进行握手 if Self.handshaken = False: #Log输出, Socket x starts with remoteClient y handshake process print ' socket%s Start handshaken with%s! '% (self.index,self.remote) #从客户端接受1kb数据, stored in buffer self.b Uffer + = SELF.CONN.RECV (1024) #如果接受数据中有 \r\n\r\n Flag If Self.buffer.find (' \r\n\r\n ')!=-1: #按照这种标志分割一次, Result: hea Der Data (Parsing of the Web page) #再对header and the data part of a separate parsing header, data = Self.buffer.split (' \r\n\r\n ', 1) #对header进行分割后, removed The n-1 section of the plane in Header.split ("\ r \ n") [1:]: #逐行的解析Request header information (key,value) Key, Value = Line.split ( ":", 1 #然后存放在一个Hash表中, easy access Headers[key] = value #人为定义Location的item的信息 #构造location: ws://localhost/p
Ath? headers["Location"] = "ws://%s%s"% (headers["Host", Self.path) print "Location:", headers["Location"] Print Hea DERs: ", headers #取出其中两项信息key1 key2 #key1 = headers[" Sec-websocket-key1 "] #key2 = headers[" Sec-websocke T-key2 "] #Header解析完毕后, analyze the data section #如果data部分长度小于8的话, and continue to receive from the client side to make it 8 bytes if Len (data) < 8:data = Self.conn.recV (8-len (data)) #将data的数据信息存放为key3变量 (first eight bytes before key3) #key3 = Data[:8] #将data后面的数据作为buffer进行存放 self.buf
fer = data[8:] #根据key1, Key2,key3 produce token. #根据客户的key1, Key2, 8-byte keyword #产生一个16位的安全秘钥 #old-protocol #token = Self.generate_token (Key1, Key2, Key3) #ne W Protocol token = generate_token_2 (self, key) #握手过程, the server constructs the handshake information, validates and matches #Upgrade: WebSocket is represented as a special HTTP request, The purpose of the request is to upgrade from the HTTP protocol to the WebSocket protocol handshake = ' \ http/1.1 Web Socket Protocol handshake\r\n\ Upgrade:websocke t\r\n\ connection:upgrade\r\n\ sec-websocket-origin:%s\r\n\ sec-websocket-location:%s\r\n\r\n\ '% ( headers[' Origin '], headers[' Location ') #服务端发送握手数据 & the token value generated by key Self.conn.send (Handshake+token) #这个
After the operation is set to the handshake state Self.handshaken = True #Log输出状态: Socket x shook hands with client y successfully. print ' socket%s handshaken with%s success! '% (self.index,self.remote) #向全部连接客户端集合发送消息, (arrival of environment Socket X) SendMessage ( ' Welcome, ' +self.name+' !') else: #如果已经握手 #从客户端读取64字节的数据 Self.buffer + = SELF.CONN.RECV (#如果数据中存在FF的标志), then decompose if self.buffer by this flag
. Find ("\xff")!=-1: #分解方式啥含义?? s = Self.buffer.split ("\xff") [0][1:] #如果消息是 ' terminate ', print Socket exits if s== ' quit ': print ' socket%s logout! '% (self . Index) #全体同志Socket退出的状态 (prepare for GUI update) SendMessage (self.name+ ' Logout ') #同时删除socket连接集合 deleteconnect Ion (str (SELF.INDEX)) #同时关闭对应的WebSocket连接 (multi-threaded Relationship) Self.conn.close () Break else: #否则输出, Socket x Collection Message to client y print ' socket%s Got msg:%s from%s! '% (self.index,s,self.remote) #向全体的客户端输出连接的信息 SendMessage ( Self.name+ ': ' +s) #Buffer信息再一次的清空 Self.buffer = "" Def generate_token_2 (Self, key): Key = key + ' 258EAFA
5-e914-47da-95ca-c5ab0dc85b11 ' Ser_key = HASHLIB.SHA1 (key). Digest () return Base64.b64encode (Ser_key) def generate_token (self, key1, Key2, Key3): #list/tuple (LS)-list tuples convert to each other #这句话没看懂, how to understand whether key isNumber NUM1 = Int ("". join ([Digit for digit in list (key1) if Digit.isdigit ())) #解析key1中空格的个数 spaces1 = Len ([Char for char I N List (key1) if char = = ""]) #解析后number2对象 num2 = Int ("". join ([Digit for digit in list (Key2) if Digit.isdigit ())) #统计 The number of spaces? security Authentication spaces2 = Len ([Char for Char ' in list (key2) if char = = "]) #按照一定的格式进行打包, and then network transfer (format can be booked by itself) #struck. Pack: http://blog.sina.com.cn/s/blog_4b5039210100f1tu.html combined = struct.pack (">ii", Num1/spaces1, Num2/spaces2) + Key3 #对打包的值进行md5解码后, and returns a binary form of # #hexdigest () is a hexadecimal value, digest () is a binary value #处理MD5: http://wuqinzhong.blog.163.com/blog/static /4522231200942225810117/return hashlib.md5 (combined). Digest () #创建WebSocket服务器对象 () class Websocketserver (object): # When initialized, the socket is null DEF __init__ (self): Self.socket = None #开启操作 def begin (self): #服务器尽心启动Log输出 print ' Websocketserver
Start! ' #创建TCP的套接字, monitor IP, Port #这里可以自己进行设置, can listen to 50 requests self.socket = Socket.socket (socket.af_inet, socket.
SOCK_STREAM) ip = ' localhost ' port = 8080
#print "WebServer is listening%s,%d"% Ip,port #self. Socket.bind (Ip,port) self.socket.bind Ket.listen #声明全局连接集合 Global connectionlist i=0 while True: #服务器响应请求, returning information to connect customers (connect FD, customer address) connection, Address = self.socket.accept () #address信息中的第1个字符串为username对象 username=address[0] #根据连接的客户信息, creating a WebSocket object (essentially a thread #连接后sockfd, connect index, user name, address Newsocket = WebSocket (connection,i,username,address) #线程启动 Newsocket.start () #更 The set of new connections (the corresponding relationship of the hash table)-NAME->SOCKFD connectionlist[' connection ' +str (i)]=connection i = i + 1 if __name__ = "__main_ _ ": Server = Websocketserver () server.begin ()
# # Client.html Page
# # Usage Instructions
websocket.py
Visit: http://localhost:8080/client.html