python websocket例程_python 实现websocket

#!/usr/bin python#-*- coding:UTF-8 -*-

importredisimporttime, threading, sched, json, socket, base64, hashlib,logging,traceback

allkv_json= "" #发送给前端的数据

conn_list = [] #处于在线的socket链接

#单例

defsingleton(cls):

instances={}def getinstatce(*args, **kwargs):if cls not ininstances:

instances[cls]= cls(*args, **kwargs)returninstances[cls]returngetinstatce

@singletonclassRedisUtils:def __init__(self, port, db):

self.redis_object= redis.Redis('127.0.0.1', port, db)

self.allKV=[]defget_all_kv(self):

keys=self.redis_object.keys()

self.allKV= [key for key in keys if self.redis_object.ttl(key) is notNone]#for key in keys:

#self.allKV[key] = 'online' if (time.time() - int(self.redis_object.get(key))) < 10 else 'off_line'

classSchedTask:

allkv=[]

@classmethoddefgetHostOnlineStatus(cls):globalallkv_json

ru= RedisUtils(6379, 1)

ru.get_all_kv()

cls.allkv=ru.allKV

allkv_json=json.dumps(cls.allkv)printallkv_json

@classmethoddefgetHostOnlineStatusTask(cls):

threading.Thread(target=cls.getHostOnlineStatus).start()

@classmethoddefrun(cls, timedelay):whileTrue:

s=sched.scheduler(time.time, time.sleep)

s.enter(timedelay,1, cls.getHostOnlineStatusTask, ())

s.run()classWebsocketUtils(threading.Thread):

MAGIC_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"\"WebSocket-Protocol:chat\r\n\r\n"

def __init__(self, host, port):if notisinstance(host, str):raise KeyError("The host must be a string like \'127.0.0.1\'")else:

self.host=hostif notisinstance(port, int):raise KeyError('The port must be a integer')else:

self.port=porttry:

self.sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)

self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)

self.sock.bind((host, port))print '========================================================================================='

printhost,port

self.sock.listen(100)except:printtraceback.format_exc()print 'start socket error'super(WebsocketUtils, self).__init__()#前端握手

defhandshake(self, conn):

headers={}

shake= conn.recv(1024)printshakeif notlen(shake):print('len error')returnFalse

header, data= shake.split('\r\n\r\n', 1)for line in header.split('\r\n')[1:]:

key, value= line.split(':', 1)

headers[key]=valueif 'Sec-WebSocket-Key' not inheaders:print('this is not websocket, client close.')printheaders

conn.close()returnFalse

sec_key= headers['Sec-WebSocket-Key']

res_key= base64.b64encode(hashlib.sha1(sec_key +WebsocketUtils.MAGIC_STRING).digest())

str_handshke= WebsocketUtils.HANDSHAKE_STRING.replace('{1}', res_key).replace('{2}',

self.host+ ":" +str(self.port))printstr_handshke

conn.send(str_handshke)

i=0defsend_msg(self):

WebsocketUtils.i+=1

globalconn_listprint 'send msg' +str(WebsocketUtils.i)for conn inconn_list:try:

conn.send('%c%c%s' % (0x81, len(allkv_json), allkv_json))except:print 'send msg error'conn.close()

conn_list.remove(conn)#定时给前端发信息

defsched_send_msg(self):whileTrue:

s=sched.scheduler(time.time,time.sleep)

s.enter(2,1,self.send_msg,())

s.run()defrun(self):#另开一个线程给各个conn发消息

globalconn_list

t=threading.Thread(target=self.sched_send_msg)

t.start()whileTrue:print 'wait link'

try:printself.sock

self.conn, addr=self.sock.accept()print 'link ok'self.handshake(self.conn)print 'handshake ok'conn_list.append(self.conn)except:printtraceback.format_exc()print 'error'time.sleep(3)if __name__ == '__main__':#websocket线程

websocket_utils = WebsocketUtils('0.0.0.0', 9000)#websocket_utils.setDaemon(True) # 把当前进程设置为守护进程,主线程执行完毕,子线程均停止

websocket_utils.start()#定时获取主机在线信息

SchedTask.run(5)

你可能感兴趣的:(python,websocket例程)