您当前的位置:首页 > IT编程 > python
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch | 异常检测 | Transformers | 情感分类 | 知识图谱 |

自学教程:Python实现网络聊天室的示例代码(支持多人聊天与私聊)

51自学网 2021-10-30 23:04:02
  python
这篇教程Python实现网络聊天室的示例代码(支持多人聊天与私聊)写得很实用,希望能帮到您。

实验名称:

网络聊天室

功能:

i. 掌握利用Socket进行编程的技术
ii. 掌握多线程技术,保证双方可以同时发送
iii. 建立聊天工具
iv. 可以和单人聊天
v. 可以和多个人同时进行聊天
vi. 使用图形界面,显示双方的语录
vii. 程序可以在一定程度上进行错误识别

概述

实验通过聊天室可以完成单人或多人之间的聊天通信,功能的实现主要是通过Socket通信来实现。本次实验采用客户端/服务器(C/S)架构模式,通过Python语言来编写服务器端与客户端的程序。运用多线程可完成多点对多点的聊天。
服务器端程序主要用于接收用户信息,消息接收与转发。
客户端程序实现用户注册登录,聊天信息显示与信息输入。

代码解释

统计当前在线人数,并且将新用户加到用户列表中。
Serve.py

在这里插入图片描述

这是服务器对于聊天服务的实现。

在这里插入图片描述

通过继承threading.Thread类而实现多线程,重写run函数。

在这里插入图片描述

接受来自客户端的用户名,如果用户名为空,使用用户的IP与端口作为用户名。如果用户名出现重复,则在出现的用户名依此加上后缀“2”、“3”、“4”……

在这里插入图片描述

在获取用户名后便会不断地接受用户端发来的消息(即聊天内容),结束后关闭连接。

在这里插入图片描述

如果用户断开连接,将该用户从用户列表中删除,然后更新用户列表。

在这里插入图片描述

将地址与数据(需发送给客户端)存入messages队列。

在这里插入图片描述

服务端在接受到数据后,会对其进行一些处理然后发送给客户端,如下图,对于聊天内容,服务端直接发送给客户端,而对于用户列表,便由json.dumps处理后发送。

在这里插入图片描述

Client.py
建立连接,发送用户名及判断是否为私聊消息,私聊用~识别

在这里插入图片描述

接受来自服务器发送的消息

在这里插入图片描述

对接收到的消息进行判断,如果是在线用户列表(用json.dumps处理过),便清空在线用户列表框,并将此列表输出在在线用户列表框中。

在这里插入图片描述

如果是聊天内容,便将其输出在聊天内容显示框中。

在这里插入图片描述

设置登录窗口

在这里插入图片描述

设置消息界面

在这里插入图片描述

设置在线用户列表。

在这里插入图片描述

完整代码:
Serve.py

import socketimport threadingimport queueimport json # json.dumps(some)打包  json.loads(some)解包import osimport os.pathimport sysIP = '127.0.0.1'PORT = 9999   # 端口messages = queue.Queue()users = []  # 0:userName 1:connectionlock = threading.Lock()def onlines():  # 统计当前在线人员  online = []  for i in range(len(users)):    online.append(users[i][0])  return onlineclass ChatServer(threading.Thread):  global users, que, lock  def __init__(self):     # 构造函数    threading.Thread.__init__(self)    self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    os.chdir(sys.path[0])# 接受来自客户端的用户名,如果用户名为空,使用用户的IP与端口作为用户名。如果用户名出现重复,则在出现的用户名依此加上后缀“2”、“3”、“4”……  def receive(self, conn, addr):       # 接收消息    user = conn.recv(1024)    # 用户名称    user = user.decode()    if user == '用户名不存在':      user = addr[0] + ':' + str(addr[1])    tag = 1    temp = user    for i in range(len(users)):   # 检验重名,则在重名用户后加数字      if users[i][0] == user:        tag = tag + 1        user = temp + str(tag)    users.append((user, conn))    USERS = onlines()    self.Load(USERS,addr)    # 在获取用户名后便会不断地接受用户端发来的消息(即聊天内容),结束后关闭连接。    try:      while True:        message = conn.recv(1024)      # 发送消息        message = message.decode()        message = user + ':' + message        self.Load(message,addr)      conn.close()    # 如果用户断开连接,将该用户从用户列表中删除,然后更新用户列表。    except:        j = 0      # 用户断开连接      for man in users:        if man[0] == user:          users.pop(j)    # 服务器段删除退出的用户          break        j = j+1      USERS = onlines()      self.Load(USERS,addr)      conn.close()# 将地址与数据(需发送给客户端)存入messages队列。  def Load(self, data, addr):    lock.acquire()    try:      messages.put((addr, data))    finally:      lock.release()      # 服务端在接受到数据后,会对其进行一些处理然后发送给客户端,如下图,对于聊天内容,服务端直接发送给客户端,而对于用户列表,便由json.dumps处理后发送。  def sendData(self): # 发送数据    while True:      if not messages.empty():        message = messages.get()        if isinstance(message[1], str):          for i in range(len(users)):            data = ' ' + message[1]            users[i][1].send(data.encode())            print(data)            print('/n')        if isinstance(message[1], list):          data = json.dumps(message[1])          for i in range(len(users)):            try:              users[i][1].send(data.encode())            except:              pass  def run(self):    self.s.bind((IP,PORT))    self.s.listen(5)    q = threading.Thread(target=self.sendData)    q.start()    while True:      conn, addr = self.s.accept()      t = threading.Thread(target=self.receive, args=(conn, addr))      t.start()    self.s.close()if __name__ == '__main__':  cserver = ChatServer()cserver.start()

Client.py

import socketimport tkinterimport tkinter.messageboximport threadingimport jsonimport tkinter.filedialogfrom tkinter.scrolledtext import ScrolledTextIP = ''PORT = ''user = ''listbox1 = '' # 用于显示在线用户的列表框show = 1 # 用于判断是开还是关闭列表框users = [] # 在线用户列表chat = '------Group chat-------' # 聊天对象#登陆窗口root0 = tkinter.Tk()root0.geometry("300x150")root0.title('用户登陆窗口')root0.resizable(0,0)one = tkinter.Label(root0,width=300,height=150,bg="LightBlue")one.pack()IP0 = tkinter.StringVar()IP0.set('')USER = tkinter.StringVar()USER.set('')labelIP = tkinter.Label(root0,text='IP地址',bg="LightBlue")labelIP.place(x=20,y=20,width=100,height=40)entryIP = tkinter.Entry(root0, width=60, textvariable=IP0)entryIP.place(x=120,y=25,width=100,height=30)labelUSER = tkinter.Label(root0,text='用户名',bg="LightBlue")labelUSER.place(x=20,y=70,width=100,height=40)entryUSER = tkinter.Entry(root0, width=60, textvariable=USER)entryUSER.place(x=120,y=75,width=100,height=30)def Login(*args):	global IP, PORT, user	IP, PORT = entryIP.get().split(':')	user = entryUSER.get()	if not user:		tkinter.messagebox.showwarning('warning', message='用户名为空!')	else:		root0.destroy()loginButton = tkinter.Button(root0, text ="登录", command = Login,bg="Yellow")loginButton.place(x=135,y=110,width=40,height=25)root0.bind('<Return>', Login)root0.mainloop()# 建立连接s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect((IP, int(PORT)))if user:  s.send(user.encode()) # 发送用户名else:  s.send('用户名不存在'.encode())  user = IP + ':' + PORT# 聊天窗口root1 = tkinter.Tk()root1.geometry("640x480")root1.title('群聊')root1.resizable(0,0)# 消息界面listbox = ScrolledText(root1)listbox.place(x=5, y=0, width=640, height=320)listbox.tag_config('tag1', foreground='red',backgroun="yellow")listbox.insert(tkinter.END, '欢迎进入群聊,大家开始聊天吧!', 'tag1')INPUT = tkinter.StringVar()INPUT.set('')entryIuput = tkinter.Entry(root1, width=120, textvariable=INPUT)entryIuput.place(x=5,y=320,width=580,height=170)# 在线用户列表listbox1 = tkinter.Listbox(root1)listbox1.place(x=510, y=0, width=130, height=320)def send(*args):	message = entryIuput.get() + '~' + user + '~' + chat	s.send(message.encode())	INPUT.set('')sendButton = tkinter.Button(root1, text ="/n发/n/n/n送",anchor = 'n',command = send,font=('Helvetica', 18),bg = 'white')sendButton.place(x=585,y=320,width=55,height=300)root1.bind('<Return>', send)def receive():	global uses	while True:		data = s.recv(1024)		data = data.decode()		print(data)		try:			uses = json.loads(data)			listbox1.delete(0, tkinter.END)			listbox1.insert(tkinter.END, "当前在线用户")			listbox1.insert(tkinter.END, "------Group chat-------")			for x in range(len(uses)):				listbox1.insert(tkinter.END, uses[x])			users.append('------Group chat-------')		except:			data = data.split('~')			message = data[0]			userName = data[1]			chatwith = data[2]			message = '/n' + message			if chatwith == '------Group chat-------':  # 群聊				if userName == user:					listbox.insert(tkinter.END, message)				else:					listbox.insert(tkinter.END, message)			elif userName == user or chatwith == user: # 私聊				if userName == user:					listbox.tag_config('tag2', foreground='red')					listbox.insert(tkinter.END, message, 'tag2')				else:					listbox.tag_config('tag3', foreground='green')					listbox.insert(tkinter.END, message,'tag3')			listbox.see(tkinter.END)r = threading.Thread(target=receive)r.start() # 开始线程接收信息root1.mainloop()s.close()

到此这篇关于Python实现网络聊天室的示例代码(支持多人聊天与私聊)的文章就介绍到这了,更多相关Python 网络聊天室内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net!


基于Python的接口自动化unittest测试框架和ddt数据驱动详解
python+selenium爬取微博热搜存入Mysql的实现方法
万事OK自学网:51自学网_软件自学网_CAD自学网自学excel、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。