用Python的socket制作聊天室

mac2024-06-23  38

前言

笔者最近也捡了捡n多年前学过的一点python基础,接触了一些socket编程,也参考了一些其他大佬的博客。

看见一个比较有趣的题目:用socket制作一个聊天室,于是自己也试着做了一下。

参考博客:https://blog.csdn.net/exmlyshy/article/details/85320971

在我的代码中我参考了上述博客的思路(客户端的脚本基本没什么改动),然后我在服务端的代码中加入了聊天记录的功能(通过写入文件),另外还有显示在线用户的功能。

程序

服务端

import socket import time # 创建UDP套接字 svrsocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 绑定 svrsocket.bind(('',8080)) # 聊天室内用户,用字典存放,{(ip:port):用户名} users = {} def send_record(msg): ''' 接收一个字符串 打印并传递给write2file和broadcast 通过该方法可在服务器和用户上看见用户进入/离开聊天室以及用户聊天信息 同时将上述信息写入文件(通过write2file) ''' print(msg) write2file(msg) broadcast(msg) def write2file(string): ''' 接收一个字符串 可将字符串作为单独的一行追加到文件末尾 用于将聊天信息记录到文件中 ''' file = open('/root/python/chat_history.txt','a') file.write(string+"\n") file.close() def broadcast(msg): ''' 在套接字中广播(给每个用户都发送msg) 把每个用户发送的信息都发送给其他用户 ''' # 遍历用户字典users for address in users: svrsocket.sendto(msg.encode(), address) while True: try: # 从UDP套接字接收到信息 user_data, user_addr = svrsocket.recvfrom(1024) # 新用户加入聊天室 if not user_addr in users: # 该用户进入聊天室的msg enter_msg = time.asctime() + "\n" + user_data.decode() + "进入聊天室..." # 该用户进入聊天室,发送提示并记录到文件 send_record(enter_msg) # 将该用户添加到用户字典users users[user_addr] = user_data.decode('utf-8') # 新用户进入聊天室,无需再判断user_data continue # 用户输入"--EXIT"退出聊天 if '--EXIT' in user_data.decode('utf-8'): # 用户离开聊天室的msg leave_msg = time.asctime() + "\n" + users[user_addr] + "离开了聊天室..." # 用户字典删除该用户 users.pop(user_addr) # 用户退出聊天室,发送提示并记录到文件 send_record(leave_msg) # 用户输入"--USERLIST"请求聊天室内在线用户列表 elif '--USERLIST' in user_data.decode('utf-8'): # 遍历存放用户的字典users for user in users.keys(): # list_msg = username+ip+port list_msg = (users[user]+': '+user[0]+":"+str(user[1])).encode() # 单独发送给请求userlist的用户 svrsocket.sendto(list_msg,user_addr) else: # 聊天室内用户正常聊天 msg = time.asctime() + '\n' +user_data.decode('utf-8') # 发送消息并记录 send_record(msg) except ConnectionResetError: print("ConnectionResetError")

客户端

import socket import threading def send(sock,addr): ''' 该函数接受一个套接字和一个元组(地址,端口) 可通过input()获取用户输入,将信息发送给套接字 ''' while True: # 获取用户输入 string = input() # 发送输入信息 message = name + ": " + string sock.sendto(message.encode('utf-8'),addr) # 用户输入exit退出聊天 if string == '--EXIT': break def recv(sock,addr): ''' 该函数接受一个套接字和一个元组(地址,端口) 可通过套接字接收服务端发过来的信息 ''' sock.sendto(name.encode('utf-8'),addr) while True: data = sock.recv(1024) print(data.decode('utf-8')) print('____WELCOME____\n'+'EXIT -> exits\nUSERLIST -> get users') # 获取用户名 name = input('please input your name:') # 建立套接字 socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 服务器IP地址为192.168.218.17,端口设置为8080 server = ('192.168.218.17',8080) # 多线程接收和发送 tr = threading.Thread(target=recv,args=(socket,server),daemon=True) ts = threading.Thread(target=send,args=(socket,server)) tr.start() ts.start() ts.join() socket.close()

效果图

总结

可以从效果图看出来,用户输入的信息和用户们的聊天记录混在一起,确实很影响用户体验,而且在聊天的时候没有任何提示符、消息的时间刷得太多同样也很影响使用。

笔者水平有限,如有错误欢迎指正!侵权必删

最新回复(0)