def dispaly_message(self): s = self.server self.user_info.insert('end', '已连接的用户:') while True: # print('当前有{0}个线程_'.format(threading.activeCount())) # for i in threading.enumerate(): # print(i) client, address = s.accept( ) #运行至此阻塞,监听用户连接,建立连接口执行下列步骤,执行完后在此处再次阻塞,监听新用户连接 self.connection_dict[ address] = client #在用户连接字典中创建一个key为(ip,端口),value为socket元素(将连接的用户对象加入到连接字典) # print(self.connection_dict) show_tips( self.display_info, self.pre_time_(), '用户: {0} 已连接,当前在线人数为{1}人'.format(address, len(self.connection_dict)), '').show() #在消息窗体显示提示信息 self.user_info.insert( 'end', '用户 :{0}'.format(address)) #将用户插入到在线用户列表listbox组建中 for connection in self.connection_dict: message = {} message['users'] = list(self.connection_dict.keys()) self.connection_dict[connection].send( json.dumps(message).encode()) #对所有用户发送在线用户列表 t = threading.Thread(target=self.receive_data, args=(address, )) #将为新加入用户建立新线程,监听用户信息 # print(t.name) t.start() #启动用户子线程
def chat_with(self): # print(self.private_message) try: user_index = self.user_info.curselection()[0] - 1 user = self.userlist[user_index] if (tuple(user) == self.connection.getsockname()): show_tips(self.display_info, self.pre_time_(), '请选择非自己的私聊的对象', '').show() else: try: chat_data = list( self.private_chat_window_dict[tuple(user)].chat_data) print('之前窗口的消息记录为:{0}'.format(chat_data)) # 若读到了该用户的历史数据,将其放入对应的历史数据list try: self.chat_historydata[tuple( user)] = chat_data + self.new_message[tuple(user)] print('更新历史聊天记录为:{0}'.format( self.chat_historydata[tuple(user)])) self.new_message[tuple(user)] = [] except: self.chat_historydata[tuple(user)] = chat_data self.create_display_window(user) except Exception as e: self.create_display_window(user) except Exception as e: # print(e) show_tips(self.display_info, self.pre_time_(), '请选择私聊的对象', '').show()
def display_private_message(self, user): try: for message in self.new_message[tuple(user)]: show_tips( self.private_chat_window_dict[tuple( user)].son_display_info, self.pre_time_(), '用户:{0}:{1}'.format(user, message), '').show() self.new_message[tuple(user)] = [] except Exception as e: print('显示消息出错')
def receive_data(self, address): while True: try: # 如果要写私聊消息的离线显示,应该创建一个离线用户字典,当用户下线时,在离线消息字典中创建key为用户的(ip, 端口),value初始为空列表 #当收到消息,并判断为私聊消息后,先遍历在线用户字典,检查私聊消息中的接受者是否在线,若不在线,则遍历离线用户字典,若在离线用户字典中找到 #接受者,则在字典中接受者key对应的value中加入私聊消息 # 每次在客户端建立连接时,遍历离线用户字典中value长度为非空的历史离线用户(这些用户存在私聊消息),若匹配上,则将用户离线列表中的消息推送给该用户。 client = self.connection_dict[address] data = client.recv(1024) # 私聊信息中含有send_to字段,而公开信息中没有, # 所以若为私聊信息则运行try中的转发私聊聊天信息代码块 try: receive_message = json.loads(data.decode()) send_to = receive_message['send_to'] send_to_tuple = tuple(send_to) message = receive_message['message'] receive_message['sender'] = address for connection in self.connection_dict: if (connection == send_to_tuple): self.connection_dict[connection].send( json.dumps(receive_message).encode() ) #若在在线用户列表中找到了私聊对象,则将信息发送给他 break self.display_info.insert('end', '{0}'.format(self.pre_time_())) self.display_info.insert( 'end', '用户: {0}对用户: {1}发送了一条私聊消息:'.format( address, send_to_tuple)) #服务端回显 self.display_info.insert('end', '{0}'.format(message)) self.display_info.insert('end', '') # 未找到send_to字段,运行except,广播共公开信息 except: show_tips(self.display_info, self.pre_time_(), '用户: {0}: {1}'.format(address, data.decode()), '').show() self.broadcast_data(address, data.decode()) #广播公开信息 #连接过程中出错,断开对应用户连接,将其移出连接用户列表,将新的在线用户列表发送给所有人 except Exception as e: print(e) address_list = list(self.connection_dict.keys()) self.user_info.delete(address_list.index(address) + 1) self.connection_dict.pop(address) show_tips( self.display_info, self.pre_time_(), '用户: {0} 已断开连接,当前在线人数为{1}人'.format( address, len(self.connection_dict)), '').show() for connection in self.connection_dict: message = {} message['users'] = list(self.connection_dict.keys()) self.connection_dict[connection].send( json.dumps(message).encode()) break
def send_message(self, *event): # self.display_info.insert('end', 'test') try: message = self.message_input.get('1.0', tkinter.END) message_length = len(message) self.message_input.delete('1.0', tkinter.END) self.connection.send(message.encode()) show_tips(self.display_info, self.pre_time_(), '{0}: {1}'.format('我', message), '').show() except Exception as e: show_tips(self.display_info, self.pre_time_(), '发送消息失败,请重试', '').show() print(e)
def log_out_user(self): try: # print(self.connection_dict) user_index = self.user_info.curselection( )[0] - 1 #在listbox组件中找到用户的索引 user_address_list = [ address for address in list(self.connection_dict.keys()) ] #客户端连接字典中的key列表 user_client = self.connection_dict[ user_address_list[user_index]] #用上面的索引和列表找到对应的哟用户socket对象 user_client.close() #关闭该socket对象 # self.connection_dict.pop(user_address[user_index]) # print(self.connection_dict) except Exception as e: print(e) show_tips(self.display_info, self.pre_time_(), '当前操作失败,请选择左侧窗体的用户', '').show() #若未选中用户的提示信息
def send_message(self, *event): # self.display_info.insert('end', 'test') try: data = self.message_input.get('1.0', tkinter.END) #获取输入栏中用户的输入信息 data_length = len(data) #获取输入信息长度 self.message_input.delete('1.0', tkinter.END) #获取万必要信息后清空输入栏 #对所有用户发送信息 for connection in self.connection_dict: #遍历连接字典,只取其中的key message = {} message['sender'] = '服务器' message['message'] = data self.connection_dict[connection].send( json.dumps(message).encode() ) #以json格式对所有用户发送输入的信息,此后所有信息都已json格式发送 show_tips(self.display_info, self.pre_time_(), '{0}: {1}'.format('我', data), '').show() #在服务器窗体显示发送的信息 except Exception as e: show_tips(self.display_info, self.pre_time_(), '发送消息失败,请重试', '').show() #发送失败提示信息 print(e)
def chat_with(self): show_tips(self.display_info, self.pre_time_(), '该部分暂未写完', '').show() #未写完提示信息
def dispaly_message(self): self.user_info.insert('end', '已连接的用户:') try: s = self.connection # self.display_info.insert('end', '{0}:{1}'.format(self.connection_class.host, 'test')) while True: receive_message = json.loads(s.recv(1024).decode()) if (len(receive_message) == 3): sender = receive_message['sender'] message = receive_message['message'] # self.new_message[tuple(sender)] = [] try: self.private_message[tuple(sender)].append( message) #尝试在私聊字典中找到该用户的私聊列表,并将新的消息加入到这个列表 try: if (self.private_chat_window_dict[tuple(sender)]. flag == True): #如果通过选中用户创建了该用户的窗体类 print('用户已开启窗口') try: self.new_message[tuple(sender)].append( message) print('新消息为:'.format( self.new_message[tuple(sender)])) except: self.new_message[tuple(sender)] = [message] self.display_private_message(sender) # print(self.private_chat_window_dict[tuple(sender)]) else: print('非第一次接收私聊消息,窗口激活过,现已关闭') show_tips( self.display_info, self.pre_time_(), '收到用户:{0}一条私聊消息(如需回复,选中用户点击私聊): '.format( sender), '').show() # print('尝试加入的消息为:{0}'.format(message)) # print('现在的消息列表为{0}'.format(self.private_message[tuple(sender)])) # self.chat_historydata[tuple(sender)] = self.private_message[tuple(sender)] try: self.new_message[tuple(sender)].append( '{0}'.format(self.pre_time_())) self.new_message[tuple(sender)].append( '用户:{0}:{1}'.format(sender, message)) self.new_message[tuple(sender)].append('') # print('新消息为:'.format(self.new_message[tuple(sender)])) except: self.new_message[tuple(sender)] = [] self.new_message[tuple(sender)].append( '{0}'.format(self.pre_time_())) self.new_message[tuple(sender)].append( '用户:{0}:{1}'.format(sender, message)) self.new_message[tuple(sender)].append('') print('新数据为{0}'.format( self.new_message[tuple(sender)])) except: #如果未选中用户创建该用户的窗体类 print('非第一次接收消息,用户任未点开私聊按钮') show_tips( self.display_info, self.pre_time_(), '收到用户:{0}一条私聊消息(如需回复,选中用户点击私聊): '.format( sender), '').show() # print(self.chat_historydata[tuple(sender)]) self.chat_historydata[tuple(sender)] = [] for msg in self.private_message[tuple(sender)]: self.chat_historydata[tuple(sender)].append( '{0}'.format(self.pre_time_())) self.chat_historydata[tuple(sender)].append( '用户:{0}:{1}'.format(sender, msg)) self.chat_historydata[tuple(sender)].append('') # print(self.chat_historydata[tuple(sender)]) except Exception as e: #如果尝试失败,则在用户私聊消息字典中新建该用户的私聊消息列表,并将新消息加入,同时初始化对应用户历史消息列表为空 self.private_message[tuple(sender)] = [] self.private_message[tuple(sender)].append(message) self.historydata[tuple(sender)] = [] # print(self.private_message[tuple(sender)]) try: if (self.private_chat_window_dict[tuple( sender)].flag == True ): #之前创建了对应用户的窗体类,但是未创建对应用户的消息类 print('第一次收到私聊消息,用户已经点击过私聊按钮') try: self.new_message[tuple(sender)].append( message) print('新消息为:'.format( self.new_message[tuple(sender)])) except: self.new_message[tuple(sender)] = [message] self.display_private_message(sender) else: #不存在未创建消息类的情况下将窗口关闭的情况。 print('程序不会走到这') except: print('第一次收到私聊消息,用户还未点击过私聊按钮' ) #既未创建对应用户窗体类,又未创建对应用户消息类 show_tips( self.display_info, self.pre_time_(), '收到用户:{0}一条私聊消息(如需回复,选中用户点击私聊): '.format( sender), '').show() # self.chat_historydata[tuple(sender)] = self.private_message[tuple(sender)] self.chat_historydata[tuple(sender)] = [] # for msg in self.private_message[tuple(sender)]: self.chat_historydata[tuple(sender)].append( '{0}'.format(self.pre_time_())) self.chat_historydata[tuple(sender)].append( '用户:{0}:{1}'.format(sender, message)) self.chat_historydata[tuple(sender)].append('') # print(self.chat_historydata[tuple(sender)]) if (len(receive_message) == 2): sender = receive_message['sender'] message = receive_message['message'] if (sender == '服务器'): show_tips(self.display_info, self.pre_time_(), '{0}: {1}'.format(sender, message), '').show() else: show_tips(self.display_info, self.pre_time_(), '用户: {0}: {1}'.format(sender, message), '').show() if (len(receive_message) == 1): users = receive_message['users'] if (len(self.userlist) <= len(users)): #每次有新加入用户就将他加入到用户列表中,并且更新userlist new_users = [ u for u in users if u not in self.userlist ] for user in new_users: if (tuple(user) == self.connection.getsockname()): self.user_info.insert('end', '我 :{0}'.format(user)) else: self.user_info.insert('end', '用户 :{0}'.format(user)) self.ord_userlist = self.userlist self.userlist = users if (len(self.userlist) >= len(users)): # 每次有离线用户时在用户列表中删除离线用户,并且更新userlist logout_users = [ u for u in self.userlist if u not in users ] for user in logout_users: self.user_info.delete( self.userlist.index(user) + 1) self.ord_userlist = self.userlist self.userlist = users except Exception as e: show_tips(self.display_info, self.pre_time_(), '连接服务器失败,请重试', '').show() self.user_info.delete(1, tkinter.END) print(e)