def run(): gen_cert() config = get_config() s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((config['server']['bind_ip'], config['server']['bind_port'])) s.listen(1) print("Server listening on " + config['server']['bind_ip'] + ":" + str(config['server']['bind_port'])) bytes_to_receive = {} bytes_received = {} data_buffer = {} while True: rlist, wlist, xlist = select.select(list(map(lambda x: x.socket, scs)) + [s], [], []) for i in rlist: if i == s: # 监听socket为readable,说明有新的客户要连入 sc = common.transmission. secure_channel.accept_client_to_secure_channel(s) socket_to_sc[sc.socket] = sc scs.append(sc) bytes_to_receive[sc] = 0 bytes_received[sc] = 0 data_buffer[sc] = bytes() continue # 如果不是监听socket,就是旧的客户发消息过来了 sc = socket_to_sc[i] if bytes_to_receive[sc] == 0 and bytes_received[sc] == 0: # 一次新的接收 conn_ok = True first_4_bytes = '' try: first_4_bytes = sc.socket.recv(4) except ConnectionError: conn_ok = False if first_4_bytes == "" or len(first_4_bytes) < 4: conn_ok = False if not conn_ok: sc.close() if sc in sc_to_user_id: user_id = sc_to_user_id[sc] # 通知他的好友他下线了 frs = database.get_friends(user_id) for fr in frs: if fr['id'] in user_id_to_sc: user_id_to_sc[fr['id']].send(MessageType.friend_on_off_line, [False, user_id]) # 通知群聊里的人 # [room_id, user_id, online] rooms_id = database.get_user_rooms_id(user_id) for room_id in rooms_id: users_id = database.get_room_members_id(room_id) for _user_id in users_id: if _user_id in user_id_to_sc and user_id != _user_id: user_id_to_sc[_user_id].send(MessageType.room_user_on_off_line, [room_id, user_id, False]) # 把他的连接信息移除 remove_sc_from_socket_mapping(sc) else: data_buffer[sc] = bytes() bytes_to_receive[sc] = struct.unpack('!L', first_4_bytes)[0] + 16 + 1 + 32 buffer = sc.socket.recv(bytes_to_receive[sc] - bytes_received[sc]) data_buffer[sc] += buffer bytes_received[sc] += len(buffer) if bytes_received[sc] == bytes_to_receive[sc] and bytes_received[sc] != 0: # 当一个数据包接收完毕 bytes_to_receive[sc] = 0 bytes_received[sc] = 0 try: data = sc.on_data(data_buffer[sc]) print(data['type']) handle_event(sc, data['type'], data['parameters']) except: pprint(sys.exc_info()) traceback.print_exc(file=sys.stdout) pass data_buffer[sc] = bytes()
def run(sc, parameters): parameters[0] = parameters[0].strip().lower() c = database.get_cursor() sql = "SELECT id,username from users where username='******' and password='******'" % ( parameters[0], md5(parameters[1])) print(sql) #r = c.execute("SELECT id,username from users where username='******' and password='******'", (parameters[0], md5(parameters[1]))) c.execute(sql) rows = c.fetchall() if len(rows) == 0: sc.send(MessageType.login_failed) return user_id = rows[0][0] # 已经登入,踢下线 if user_id in user_id_to_sc: sc_old = user_id_to_sc[user_id] sc_old.send(MessageType.server_kick) sc_old.close() remove_sc_from_socket_mapping(sc_old) sc_to_user_id[sc] = user_id user_id_to_sc[user_id] = sc user = database.get_user(user_id) sc.send(MessageType.login_successful, user) login_bundle = {} # 发送群列表 rms = database.get_user_rooms(user_id) login_bundle['rooms'] = list(map(lambda x: add_target_type(x, 1), rms)) # for rm in rms: # sc.send(MessageType.contact_info, add_target_type(rm, 1)) # 发送好友请求 frs = database.get_pending_friend_request(user_id) for fr in frs: sc.send(MessageType.incoming_friend_request, fr) # 发送好友列表 frs = database.get_friends(user_id) login_bundle['friends'] = list(map(lambda x: add_target_type(x, 0), frs)) for fr in frs: # sc.send(MessageType.contact_info, add_target_type(fr, 0)) # 通知他的好友他上线了 if fr['id'] in user_id_to_sc: user_id_to_sc[fr['id']].send(MessageType.friend_on_off_line, [True, user_id]) # 通知群聊里的人他上线了 # [room_id, user_id, online] rooms_id = database.get_user_rooms_id(user_id) for room_id in rooms_id: users_id = database.get_room_members_id(room_id) for _user_id in users_id: if _user_id in user_id_to_sc and user_id != _user_id: user_id_to_sc[_user_id].send(MessageType.room_user_on_off_line, [room_id, user_id, True]) login_bundle['messages'] = database.get_chat_history(user_id) sc.send(MessageType.login_bundle, login_bundle)