服务器端代码

import socket
import pickle
import _pickle
import copy
from threading import Thread
import time

class TcpServer:
	def __init__(self):
		self.server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
		self.server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)		
		self.server.setblocking(0)
		self.server_ip = \'\'
		self.server_port = 55555

		self.run_thread = None
		self.send_user_thread = None

		self.client_dict = {}
		self.old_online_client = {}
		self.new_online_client = {}
	def send_onlie_user(self):
		msg_online_user = {
			\'flag_user\':None,
			\'online_user_dict\':self.new_online_client,
			}
		print(msg_online_user)
		for client_f in self.client_dict:
			try:
				client_f.send(pickle.dumps(msg_online_user))
			except Exception as e:
				print(e)
			else:
				print(\'发送成功\')

	def get_online_user(self):	
		while True:
			time.sleep(5)
			print(\'收集在线用户...\')
			self.new_online_client = {}
			for client in self.client_dict:
				user_account = self.client_dict[client][\'user_info\'][\'user_account\']
				user_nickname = self.client_dict[client][\'user_info\'][\'user_nickname\']
				if user_account and user_nickname:
					self.new_online_client[user_account] = user_nickname

			else:
				if self.old_online_client == self.new_online_client:
					continue					
				print(\'正在刷新在线用户...\')
				self.send_onlie_user()
			self.old_online_client = self.new_online_client
	def run(self):
		print(\'Server open ...\')
		
		while True:
			try:
				try:
					client,self.client_addr = self.server.accept()
				except BlockingIOError:
					pass
				else:
					client.setblocking(0)
					print(\'[%s] Already Connect...\'%(self.client_addr,))
					self.client_dict[client] = {
							\'user_info\':{
								\'user_account\':None,
								\'user_nickname\':None,
							},
							\'user_msg\':{
								\'user_to\':None,
								\'user_massage\':None,
							},
					}
				client_dict_bak = copy.copy(self.client_dict)
				for client in client_dict_bak:
					if client in self.client_dict:
						try:
							self.recv_data = pickle.loads(client.recv(1024))
						except BlockingIOError:
							pass
						except _pickle.UnpicklingError:
							print(\'[E] 接收到无效数据\')
							del self.client_dict[client]
							client.close()
						except EOFError:
							print(\'用户断开..\')
							del self.client_dict[client]
							client.close()
						except Connecti Error:
							print(\'用户断开..\')
							del self.client_dict[client]
							client.close()
						else:
							if \'only\' in self.recv_data:
								self.check()

							if \'massage\' in self.recv_data:
								from_account = self.client_dict[client][\'user_info\'][\'user_account\']
								from_nickname = self.client_dict[client][\'user_info\'][\'user_nickname\']

								if not from_account and not from_nicknmae:
									print(\'违规用户..\')
									del self.client_dict[client]
									client.close()
								else:
									to_msg = self.recv_data[\'to_msg\']
									to_account = self.recv_data[\'to_account\']
									print(\'[%s]--->[%s]\\n%s\'%(from_account,to_account,to_msg))
									for client_recv in self.client_dict:
										user_account = self.client_dict[client_recv][\'user_info\'][\'user_account\']
										if user_account == to_account:
											msg_forward = {
												\'to_msg\':to_msg,
												\'from_account\':from_account,
												\'from_nickname\':from_nickname,
											}
											client_recv.send(pickle.dumps(msg_forward))
											break
							if \'alive\' in self.recv_data:
								print(\'我还活着...\')
								ack = {
									\'ack\':None,
								}
								client_recv.send(pickle.dumps(ack))
			except KeyboardInterrupt:
				break
		del self
			
	def check(self):
		first_check_repeat = {
			\'only\':None,
			\'flag\':None,
			\'m\':None,
		}
		client_account_list = []
		for client in self.client_dict:
			user_account = self.client_dict[client][\'user_info\'][\'user_account\']
			if user_account:
				client_account_list.append(user_account)

		client_account = self.recv_data[\'account\']
		client_nickname = self.recv_data[\'nickname\']
		if str(client_account) in client_account_list:
			first_check_repeat[\'flag\'] = False
			print(\'用户[%s]已被踢出服务器...\'%(self.client_addr,))
			first_check_repeat[\'m\'] = \'账户已被登陆,换个试试吧\'
			client.send(pickle.dumps(first_check_repeat))							
			del self.client_dict[client]	
			client.close()
		else:
			self.client_dict[client][\'user_info\'][\'user_account\'] = client_account
			self.client_dict[client][\'user_info\'][\'user_nickname\'] = client_nickname
			print(self.client_dict[client])
			first_check_repeat[\'flag\'] = True
			client.send(pickle.dumps(first_check_repeat))

	def __call__(self):
		self.server.bind((self.server_ip,self.server_port))
		self.server.listen(5)

		self.run_thread = Thread(target=self.run)
		self.send_user_thread = Thread(target=self.get_online_user)

		self.run_thread.start()
		self.send_user_thread.start()

	def __del__(self):
		if self.client_dict:
			msg = {
				\'close\':\'服务器即将关闭!\',
			}
			for client in self.client_dict:
				client.send(pickle.dumps(msg))
				client.close()

		self.run_thread.join()
		self.send_user_thread.join()

		self.server.close()


def main():
	s = TcpServer()
	s()

if __name__ == \'__main__\':
	main()


客户端代码

import pickle
from threading import Thread
import socket
from multiprocessing.pool import ThreadPool
import tkinter
import tkinter.messagebox as messagebox
import time

class Chat:
	def __init__(self,client,nickname):
		self.root = tkinter.Tk()
		self.client = client 
		self.nickname = nickname
		self.root. (\'欢迎你:%s\'%(nickname))
		
		self. _left_top = tkinter. (width=380,height=270)
		self. _left_center = tkinter. (width=380,height=100)
		self. _left_bottom = tkinter. (width=380,height=30)
		self. _right = tkinter. (width=170,height=400)

		self.online_user_list = tkinter.Listbox(self. _right,width=170,height=22)
		self.online_user_list.bind(\'<Double-Button-1>\',self.get_talk_user)

		self.msg_list_text = tkinter.Text(self. _left_top)
		self.msg_list_text.tag_configure(\'green\',foreground=\'#008B00\')

		self.msg_send_text = tkinter.Text(self. _left_center)
		self.msg_send_button = tkinter.Button(self. _left_bottom,text=\'发送\',command=self.send_user_msg)
		
		self. _left_top.grid(row=0,column=0,padx=2, pady=5)
		self. _left_center.grid(row=1,column=0, padx=2,pady=5)
		self. _left_bottom.grid(row=2,column=0)
		self. _right.grid(row=0,column=1,rowspan=3,padx=5,pady=5)

		self. _left_top.grid_propagate(0)
		self. _left_center.grid_propagate(0)
		self. _left_bottom.grid_propagate(0)
		self. _right.grid_propagate(0)

		self.msg_list_text.grid()
		self.msg_send_text.grid()
		self.msg_send_button.grid(sticky=tkinter.E)
		self.online_user_list.grid()

		self.tp = ThreadPool(5)

		self.talk_user = \'\'
		self.running = True
		self.tp.apply_async(func=self.recv_msg)
		#self.tp.apply_async(func=self.running_true)
		self.root.mainloop() #开启窗口
	
	def recv_msg(self):
		while True:
			try:
				repeat_ = pickle.loads(self.client.recv(1024))
			except Connecti Error:
				messagebox.showerror( =\'抱歉\',message=\'与服务器失去了连接!\')
				break
			except Exception as e:
				print(e)
				messagebox.showerror( =\'抱歉\',message=\'服务器出问题了!\')
				break
			else:
				if \'flag_user\' in repeat_:
					print(\'接收到了用户列表\')
					user_dict = repeat_[\'online_user_dict\']
					self.tp.apply_async(self.refer_user_list,args=(user_dict,))
				if \'to_msg\' in repeat_:
					print(\'收到消息\')
					to_msg = repeat_[\'to_msg\']
					from_account = repeat_[\'from_account\']
					from_nickname = repeat_[\'from_nickname\']
					self.tp.apply_async(self.show_online_user,args=(from_account,from_nickname,to_msg))
				if \'ack\' in repeat_:
					print(\'server alive ..\')
					self.running = True
				if \'close\' in repeat_:
					msg = repeat_[\'close\']
					messagebox.showerror( =\'抱歉\',message=msg)
					break
	
	def show_online_user(self,from_account,from_nickname,to_msg):
		msgcontext = time.strftime(\'%Y-%m-%d %H:%M:%S\',time.localtime())+\'\\n\'
		self.msg_list_text.insert(tkinter.END,\'%s(%s)%s\'%(from_account,from_nickname,msgcontext))
		self.msg_list_text.insert(tkinter.END,to_msg)

	def refer_user_list(self,user_dict):
		self.online_user_list.delete(0,tkinter.END)
		for user_account in user_dict:
			self.online_user_list.insert(
				tkinter.END,
				\'%s:%s\'%(user_account,user_dict[user_account])
				)			
	
	def check_alive(self):
		while True:
			time.sleep(5)
			server_alive = {
				\'alive\':None,
			}
			self.client.send(pickle.dumps(server_alive))
	
	def running_true(self):
		print(\'开启服务器检测...\',self.running)
		while True:
			time.sleep(5)
			if self.running:
				self.runing = False
				self.check_alive()
			else:
				messagebox.showerror( =\'抱歉\',message=\'服务器出问题了!\')
	
	def get_talk_user(self,event):
		name = self.online_user_list.get(self.online_user_list.curselection()[0])
		self.talk_user = name.split(\':\')[0]

	def send_user_msg(self):
		print(\'发送消息\')
		if not self.talk_user:
			return
		send_msg = self.msg_send_text.get(\'0.0\',tkinter.END)
		self.msg_send_text.delete(\'0.0\',tkinter.END)
		msg = {
			\'massage\':None,
			\'to_msg\':send_msg,
			\'to_account\':self.talk_user,
		}
		try:
			self.client.send(pickle.dumps(msg))
		except Connecti Error:
			messagebox.showerror( =\'抱歉\',message=\'与服务器失去了连接!\')
		except Connecti edError:
			messagebox.showerror( =\'抱歉\',message=\'服务器已关闭!\')
		else:
			msgcontext = time.strftime(\'%Y-%m-%d %H:%M:%S\',time.localtime())+\'\\n\'
			self.msg_list_text.insert(tkinter.END,msgcontext,\'green\')
			self.msg_list_text.insert(tkinter.END,send_msg)
class Login:
	def __init__(self):
		self.root = tkinter.Tk()
		self.root. (\'登陆\')
		self.root.resizable(height=False,width=False)

		self.root_width = 270
		self.root_height = 110

		self.screen_width = self.root.winfo_screenwidth()
		self.screen_height = self.root.winfo_screenheight()
		self.root.geometry(\'%dx%d+%d+%d\'%(
			self.root_width,
			self.root_height,
			(self.screen_width - self.root_width) / 2,
			(self.screen_height - self.root_height) /2 ,
			))
		self.lable_account = tkinter.Label(self.root,text=\'Account:\')
		self

					
				
收藏 打印
您的足迹: