这学期我们网络编程这门课主要是Window Socket,并且还是用我们没学过C++实现的,不过值得庆幸的是老师上课讲的很仔细,并且他讲课主要是讲思想,实现思路,最后老师没有限制我们课程设计使用的语言。权衡了一下,我使用Python实现了多人在线聊天的聊天室。

这个聊天室的主要功能是:

1、多人聊天——群聊

2、私聊

3、发表情包

有种仿QQ和微信聊天的感觉,但是界面不太美观,功能没那么强大,但是用作网络编程的课程设计大作业还是OK的......

这个小项目首先是在b站看的教学视频,这个教程就只实现多人聊天的功能后面我要在这个基础上实现了私聊发表情的功能,源码我会放到文章的最后,有需要的可以下载......

这篇文章主要是讲和教程不一样的地方,详细可以看一下的教学视频,或是自己下载源码学习.....

教学视频连接:

【python项目实战】创作自己的多人聊天室_哔哩哔哩_bilibili

一、服务端

服务端主要是在处理客户端请求的死循环中,添加了一个判断,判断是否要进入私聊的聊天模式

    def request_handle(self, client_sock):"""处理客户端请求"""while True:"""1、接收客户端请求"""recv_data = client_sock.recv_data()if not recv_data:  # 如果收到空字符串 就表示结束聊天self.remove_offline_user(client_sock)client_sock.close()breakprint("客户端发送的请求信息:%s" % recv_data)"""2、解析客户端请求"""parser_data = self.parser_request_text(recv_data)print("解析过的数据为:%s" % parser_data)"""3、判断请求类型,调用请求对应的处理函数"""handle_function = self.request_handle_function.get(parser_data["request_id"])if handle_function:handle_function(client_sock, parser_data)#处理聊天请求def request_chat_handle(self, client_sock, request_data):print("正在处理聊天请求~")username = request_data['username']messages = request_data['messages']chat = request_data['chat']nickname = self.clients[username]['nickname']msg = ResponseProtocol.response_chat(nickname, messages, str(self.users), chat)if chat == '------------------群聊------------------':for u_name, info in self.clients.items():if username == u_name:continueinfo['sock'].send_data(msg)else:for u_name, info in self.clients.items():if username == u_name:continueelif chat == info['nickname']:info['sock'].send_data(msg)

二、客户端

客户端的代码有较大的变化

首先是图形界面:

聊天界面的主要变化

    def append_message(self, sender, messages, chat):"""追加聊天内容到chat_text_area"""send_time = strftime("%Y-%m-%d %H:%M:%S", localtime(time()))send_info = "%s: %s\n" % (sender, send_time)# 判断是不是表情  如果字典里有则贴图if messages in self.dic:if chat == '------------------群聊------------------':self.children['chat_text_area'].insert(END, send_info, 'green')  # END将信息加在最后一行self.children['chat_text_area'].image_create(END, image=self.dic[messages])self.children['chat_text_area'].insert(END, "\n")self.children['chat_text_area'].see(END)else:self.children['chat_text_area'].insert(END, send_info, 'blue')  # END将信息加在最后一行self.children['chat_text_area'].image_create(END, image=self.dic[messages])self.children['chat_text_area'].insert(END, "\n")self.children['chat_text_area'].see(END)else:if chat == '------------------群聊------------------':self.children['chat_text_area'].insert(END, send_info, 'green')  # END将信息加在最后一行self.children['chat_text_area'].insert(END, "  " + messages + "\n")self.children['chat_text_area'].see(END)else:  # 显示私聊self.children['chat_text_area'].insert(END, send_info, 'blue')  # END将信息加在最后一行self.children['chat_text_area'].insert(END, "  " + messages + "\n")self.children['chat_text_area'].see(END)  # 显示在最后

登录界面:


from tkinter import Tk
from tkinter import Label
from tkinter import Entry
from tkinter import Button
from tkinter import ENDclass WindowLogin(Tk):def __init__(self):super(WindowLogin, self).__init__()# 初始化窗口self.window_init()# 添加控件self.add_widgets()def window_init(self):self.title('登录')self.resizable(False, False)window_width = 450window_height = 300screen_width = self.winfo_screenwidth()screen_height = self.winfo_screenheight()position_x = (screen_width - window_width) / 2position_y = (screen_height - window_height) / 2# 设置窗体大小和位置self.geometry("%dx%d+%d+%d" % (window_width, window_height, position_x, position_y))def add_widgets(self):login_title = Label(self, fg="black", font=('宋体', 20))login_title["text"] = "在 线 聊 天 室 登 录"login_title.place(x=80, y=30)username_label = Label(self)username_label["text"] = "用户名:"username_label.place(x=90, y=130)username_entry = Entry(self, name='username_entry')username_entry["width"] = 30username_entry.place(x=150, y=130)password_label = Label(self)password_label["text"] = "密   码:"password_label.place(x=90, y=170)password_entry = Entry(self, name='password_entry')password_entry["width"] = 30password_entry["show"] = "*"password_entry.place(x=150, y=170)reset_button = Button(self, name='reset_button', bg="#00BFFF", fg="white", font=('宋体', 12))reset_button["text"] = " 重 置 "reset_button.place(x=130, y=210)login_button = Button(self, name='login_button', bg="#00BFFF", fg="white", font=('宋体', 12))login_button["text"] = " 登 录 "login_button.place(x=240, y=210)def on_login_click(self, command):login_button = self.children["login_button"]login_button["command"] = commanddef on_reset_click(self, command):reset_button = self.children["reset_button"]reset_button["command"] = commanddef get_username(self):return self.children["username_entry"].get()def get_password(self):return self.children["password_entry"].get()def clear_username(self):return self.children["username_entry"].delete(0, END)def clear_password(self):return self.children["password_entry"].delete(0, END)def on_window_closed(self, command):self.protocol('WM_DELETE_WINDOW', command)if __name__ == '__main__':window = WindowLogin()window.mainloop()

客户端主要功能的变化:

from tkinter import END, Button, FLATfrom window_login import WindowLogin
from request_protocol import RequestProtocol
from client_socket import ClientSocket
from threading import Thread
from config import *
from tkinter.messagebox import showinfo
from window_chat import WindowChat
import sysclass Client:def __init__(self):# 初始化用户名 用于保存在线用户self.username = Noneself.users = set()  # 在线用户列表self.pri_user = ''  # 私聊对象self.chat = '------------------群聊------------------'  # 聊天对象, 默认为群聊# 初始化登录界面self.window = WindowLogin()self.window.on_window_closed(self.exit)"""重置按钮 和 登录按钮 的事件处理"""self.window.on_reset_click(self.clear_inputs)self.window.on_login_click(self.send_login_data)# 初始化聊天界面self.window_chat = WindowChat()self.window_chat.withdraw()  # 隐藏聊天窗口 等登陆成功后再显示self.window_chat.on_window_closed(self.exit)self.window_chat.on_eBut_click(self.express)# 在显示用户列表框上设置绑定事件self.window_chat.children['chat_count'].bind('<ButtonRelease-1>', self.privat_user)"""发送信息按钮的 事件处理函数"""self.window_chat.on_send_button_click(self.send_chat_data)self.window_chat.on_reset_button_click(self.reset_chat_data)# 创建套接字self.conn = ClientSocket()self.response_handle_function = {}self.register(RESPONSE_LOGIN_RESULT, self.response_login_handle)self.register(RESPONSE_CHAT, self.response_chat_handle)def register(self, response_id, handle_function):self.response_handle_function[response_id] = handle_functiondef startup(self):self.conn.connect()  # 自动连接服务器Thread(target=self.response_handle).start()  # 开启多线程实现数据接收self.window.mainloop()def clear_inputs(self):self.window.clear_username()self.window.clear_password()def send_login_data(self):# 获取用户名 和 密码username = self.window.get_username()password = self.window.get_password()# 封装请求信息request_text = RequestProtocol.request_login_result(username, password)# 蒋请求信息发送给服务器print("客户端的请求登录的信息为:" + request_text)self.conn.send_data(request_text)# print(self.conn.recv_data())def send_chat_data(self):msg = self.window_chat.get_inputs()self.window_chat.clear_inputs()print("%s" % msg)# 封装数据 发送到服务端request_text = RequestProtocol.request_chat_result(self.username, msg, self.chat)self.conn.send_data(request_text)# 自己界面显示的信息self.window_chat.append_message("我", msg, self.chat)def mark(self, exp):  # 参数是发的表情图标记, 发送后将按钮销毁msg = exprequest_text = RequestProtocol.request_chat_result(self.username, msg, self.chat)self.window_chat.append_message("我", msg, self.chat)self.conn.send_data(request_text)self.window_chat.b1.destroy()self.window_chat.b2.destroy()self.window_chat.b3.destroy()self.window_chat.b4.destroy()self.window_chat.ee = 0# 四个对应的函数def bb1(self):self.mark('aa**')def bb2(self):self.mark('bb**')def bb3(self):self.mark('cc**')def bb4(self):self.mark('dd**')def express(self):if self.window_chat.ee == 0:self.window_chat.ee = 1self.window_chat.b1 = Button(self.window_chat, image=self.window_chat.p1, command=self.bb1, relief=FLAT,bd=0)self.window_chat.b2 = Button(self.window_chat, image=self.window_chat.p2, command=self.bb2, relief=FLAT,bd=0)self.window_chat.b3 = Button(self.window_chat, image=self.window_chat.p3, command=self.bb3, relief=FLAT,bd=0)self.window_chat.b4 = Button(self.window_chat, image=self.window_chat.p4, command=self.bb4, relief=FLAT,bd=0)self.window_chat.b1.place(x=10, y=333)self.window_chat.b2.place(x=80, y=333)self.window_chat.b3.place(x=150, y=333)self.window_chat.b4.place(x=220, y=333)else:self.window_chat.ee = 0self.window_chat.b1.destroy()self.window_chat.b2.destroy()self.window_chat.b3.destroy()self.window_chat.b4.destroy()def reset_chat_data(self):self.window_chat.clear_inputs()def response_handle(self):while True:msg = self.conn.recv_data()if not msg:self.conn.close()breakprint("服务端返回的消息:%s" % msg)# 解析数据response_data = self.parser_response_data(msg)handle_function = self.response_handle_function[response_data['response_id']]if handle_function:handle_function(response_data)# 接收到的是在线用户列表self.window_chat.children['chat_count'].delete(0, END)  # 清空列表框number = ('     在线人数: ' + str(len(self.users)) + ' 人')self.window_chat.children['chat_count'].insert(END, number)self.window_chat.children['chat_count'].itemconfig(END, fg='green', bg="#f0f0ff")self.window_chat.children['chat_count'].insert(END, '------------------群聊------------------')self.window_chat.children['chat_count'].itemconfig(END, fg='green')for i in range(len(self.users)):self.window_chat.children['chat_count'].insert(END, (list(self.users)[i]))self.window_chat.children['chat_count'].itemconfig(END, fg='green')def parser_response_data(self, msg):# 两种数据类型 登录1001|登陆结果|昵称|username  聊天 1002|昵称|messagesresponse_data_list = msg.split(DELIMITER)response_data = {}response_data['response_id'] = response_data_list[0]if response_data['response_id'] == RESPONSE_LOGIN_RESULT:response_data['result'] = response_data_list[1]response_data['nickname'] = response_data_list[2]response_data['username'] = response_data_list[3]self.users = eval(response_data_list[4])print(self.users)elif response_data['response_id'] == RESPONSE_CHAT:response_data['nickname'] = response_data_list[1]response_data['messages'] = response_data_list[2]self.users = eval(response_data_list[3])self.chat = response_data_list[4]return response_datadef response_login_handle(self, response_data):print("客户端正在处理登录:%s" % response_data)result = response_data['result']if result == '0':showinfo("登录失败", "登录失败,用户名或密码错误!")print("登陆失败!")return# 登陆成功 获取昵称和用户名showinfo("登陆成功", "登陆成功!")nickname = response_data['nickname']self.username = response_data['username']self.window_chat.set_title(nickname)self.window_chat.update()self.window_chat.deiconify()  # 登陆成功 显示聊天界面self.window.withdraw()  # 登录成功 隐藏登录界面def response_chat_handle(self, response_data):print("客户端正在处理聊天信息:%s" % response_data)sender = response_data['nickname']messages = response_data['messages']self.window_chat.append_message(sender, messages, self.chat)# 设置私聊时的窗体标题def privat_user(self, response_data):# 获取点击的索引然后得到内容(用户名)indexs = self.window_chat.children['chat_count'].curselection()index = indexs[0]self.chat = self.window_chat.children['chat_count'].get(index)# 修改客户端名称if self.chat == '------------------群聊------------------':self.window_chat.set_title(self.username)returnti = '我' + '  -->  ' + self.chatself.window_chat.set_title(ti)return self.chatdef exit(self):self.conn.close()sys.exit(0)  # 关闭程序

源码地址: 网络编程课程设计.rar-Python文档类资源-CSDN下载

多人在线聊天室,可私聊可发表情包哟~相关推荐

  1. SpringBoot与webSocket实现在线聊天室——实现私聊+群聊+聊天记录保存

    SpringBoot与webSocket实现在线聊天室--实现私聊+群聊+聊天记录保存 引用参考:原文章地址:https://blog.csdn.net/qq_41463655/article/det ...

  2. rudesocket如何使用_[WebSocket入门]手把手搭建WebSocket多人在线聊天室(SpringBoot+WebS...

    前言 本文中搭建了一个简易的多人聊天室,使用了WebSocket的基础特性. 源代码来自老外的一篇好文: 本文内容摘要: 初步理解WebSocket的前后端交互逻辑 手把手使用 SpringBoot ...

  3. 如何简单的创建一个多人在线聊天室

    学习目标: 在本教程中,我们将要使用PHP和jQuery创建一个简单的在线聊天工具. 这种实用性的模块对于你想要有实时在线客户支持系统的网站可以说是完美. 废话不多说直接开始. 步骤1:HTML的代码 ...

  4. Unity联网之使用Socket简单实现多人在线聊天室(一)

    「前言」 之前在一直在写lua联网等一些知识,虽然lua重要,但C#联网也必不可少是吧.所以呢,本篇博客就主要介绍如何使用Unity和C#在实现多人在线聊天室. 服务器 客户端工作原理:(通过消息类型 ...

  5. Python+django网页设计入门(20):使用WebSocket创建多人在线聊天室

    2019年3月8日-10日公众号送书活动:中小学生Python课应该学什么 ================ 前导课程: Python+django网页设计入门(19):创建新模型扩展自带用户表的字段 ...

  6. MFC多人在线聊天室

    我已经在我的资源里上传了这个聊天室的代码了 基于MFC的C++的select模型的TCP聊天室 采用select网络模型,支持多人同时登陆,功能有上线.下线.群聊.私聊 使用CjsonObject进行 ...

  7. java怎么实现踢掉在线用户_Java多人在线聊天室(3)— 踢人下线功能

    作为一个聊天室,肯定会有很多人在里面聊天,那么要是有人里面捣乱怎么办?直接踢人不解释. 我们在创建数据库的时候就有这样的考虑,所以我们的账户有两种,一种是管理员,一种是普通用户. 打开的数据库!我们可 ...

  8. JS实现简易多人在线聊天室

    一.设计要求: 1)用户应通过用户名,密码登录聊天室 2)聊天室可以显示所有在线用户 3)在每一条聊天内容之前,显示发出这条聊天内容的用户名. 4)聊天室可以用web,客户端,或者纯文本方式实现. 5 ...

  9. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-完整应用例子-在线聊天室系统-代码解析...

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍一文之中我们对AgileEAS.NET S ...

最新文章

  1. PandaOCR中文版+使用教程
  2. win10 x64+anaconda+labelme标注数据
  3. 人口吸引力超宁波、南京,这座背靠上海的小城开挂了?
  4. 软件测试工程师和WGT,软件系统测试(WGT)工程师---ATK
  5. 如何建立有效的数据挖掘步骤
  6. ERP和进销存系统区别是什么
  7. 使用教育邮箱享正版Jetbrains 套件,IDEA正版webstrom正版
  8. 软件测试人员能力模型
  9. 今日得闲,完善一下之前用python画的滑稽笑脸的代码,附计算过程
  10. windows不支持scp指令解决方案
  11. 深度学习二分类问题--IMDB数据集
  12. 对等商务_对等| 第2部分
  13. 学习Vue3 第二十五章(TSX)
  14. 9月15日相约苏州丨共同探讨数智化时代,国产数据库的技术创新与实践
  15. Qt中textEdit文本编辑区设置滚动条自动向下滑落
  16. 记录大疆研发管理岗初面
  17. UCEs(超保守元件)常见问题,系统发育和进化研究新方法(即用型脊椎动物(辐鳍鱼类,鲈形目,骨鳔类) 无脊椎动物(蛛形纲,蜘蛛目,鞘翅目,双翅目,半翅目,膜翅目,鳞翅目)UCE探针,其他可定制)
  18. php unhtml包,JavaScript 版本的 PHP serialize/unse_js
  19. iOS 加密算法之MD5加密使用
  20. zk4元年拆解_减配实锤!Kobe4 开箱+拆解:你凭什么叫Protro?

热门文章

  1. 震惊!!女士们注意了:国家发布的禁用化妆品
  2. [linux学习](linuxprobe课程)二 常见的命令
  3. 02讲 | STM32单片机实现LED灯反转
  4. 使用miniconda创建Python环境
  5. 安装Fedora系统和一些系统配置
  6. Jenkins自动清理构建历史
  7. 获取地址栏倒数第一个“/”和倒数第二个之间“/”的数值
  8. 真是想不到系列之一:VB到底为我们做了什么?
  9. 《花雕学AI》你不知道的AI 机器人:29个让你大开眼界的事实
  10. iconfont的用法