服务器端代码
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
继续阅读与本文标签相同的文章
下一篇 :
设计模式——单例模式
-
靠颜值进站!刷脸支付与轨道交通的大联合
2026-05-18栏目: 教程
-
打通“最后一公里”送药地图 访海派医药集团总经理张翔
2026-05-18栏目: 教程
-
上海首个保税展示展销场所亮相 海外商品“全球同质同价”
2026-05-18栏目: 教程
-
微信聊天记录导出excel使用方法分享卓师兄微信恢复大师
2026-05-18栏目: 教程
-
用好SmartArt,快速制作美观工整的PPT
2026-05-18栏目: 教程
您的足迹:
