#!/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)