基于Python的聊天室

本文介绍了一个基于Python的聊天室项目,利用tkinter、threading和socket库,实现了用户登录、群聊、私聊及发送表情等功能。系统采用Tcp协议,服务器端负责存储用户连接信息,客户端通过服务器转发消息。
摘要由CSDN通过智能技术生成

基于Python的聊天室

摘要

本项目是一个在线的聊天室项目,主要运用了python的tkinter图形库、threading多线程库,以及soket库实现网络聊天室,主要实现了群聊和私聊功能,还有发送表情包功能。项目分为服务器端和客户端,采用Tcp协议进行网络数据传输。服务端主要用于存放用户连接信息包括用户的ip地址和端口和用户信息,客户端发送消息时经过服务器转发給其他用户。

一、引言

1.1 背景和意义

随着互联网时代的到来,人与人之间的联系更加紧密。在现实生活中需要一个契机才有机会进行深入的沟通,人们对彼此的了解仅仅是浅层的,而在线的聊天则可以让我们抛开一切外在的东西,用语言去了解一个人的内在。

1.2 系统要实现的功能

1.2.1 用户登录

用户使用默认的服务器端口地址,输入昵称,接着点击‘登录’按钮,实现登录聊天系统。

1.2.2 群发消息

用户点击‘用户列表’,然后点击‘群发’,输入信息后点击‘发送’按钮实现群发消息。

1.2.3 一对一聊天

用户点击‘用户列表’,然后点击发送的对象,此时聊天窗口的标题变为当前用户指向目标用户,此时输入信息后点击‘发送’按钮实现一对一聊天。

1.2.4 发送表情

用户点击‘表情’按钮,此时点击需要发送的表情即可发送

二、系统结构

2.1 系统结构图

本项目分为服务器端和客户端,采用Tcp协议进行网络数据传输。服务端主要用于存放用户连接信息包括用户的ip地址和端口和用户信息,如下图所示
图2.1.1

2.2 系统实现原理

系统采用C/S模式进行实现

2.2.1服务器端实现原理

登录和接收数据实现原理 :采用tcp协议,对8888端口进行监听,每当客户端的连接请求到来时,为其创建一个新的线程,判断该连接的用户是否在服务器的在线用户数组中,若不存在,则将用户的信息和用户的连接封装为一个在线用户存入用户数组中;若存在用户,则此次连接必然为发送数据的连接,因而服务器对客户端发送过来的数据进行解析,解析出其中的消息和用户

发送数据实现原理:服务端启动时,创建一个新的线程,用于监听消息队列中的数据是否为空,如果不为空,则调用发送数据的函数,以此往复。

2.2.2 客户端实现原理

发送数据实现原理:客户端数据以(消息内容:;当前用户:;目标用户)
的格式发送给服务器端,由服务器将消息转发给目标用户。

接收数据实现原理:客户端接收到数据以后,对数据进行解析,判断其是否为表情消息,若是则在存有表情的字典中找到其对应的图片,将其显示到聊天信息中;若不是表情,则直接将消息显示到聊天信息中。

2.3 系统技术分析

2.3.1 tkinter 图形用户界面库

Tkinter: Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 Macintosh系统里。Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。

2.3.2 threading 多线程

​ 每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。

​ 指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
多线程详细介绍

2.3.3 socket 网络编程

​ Python 提供了两个级别访问的网络服务。

​ 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets
API,可以访问底层操作系统Socket接口的全部方法。

​ 高级别的网络服务模块 SocketServer,它提供了服务器中心类,可以简化网络服务器的开发。

​ Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

Python 中,我们用 socket()函数来创建套接字,语法格式如下:

socket.socket([family[, type[, proto]]])

参数:

family: 套接字家族可以使AF_UNIX或者AF_INET

type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAMSOCK_DGRAM

protocol: 一般不填默认为0.

三、实现代码

3.1服务器端代码

3.1.1确定全局变量

IP = ''
PORT = 8888
que = queue.Queue()            # 用于存放客户端发送的信息的队列
users = []                     # 用于存放在线用户的信息  [conn, user, addr]
lock = threading.Lock()        # 创建锁, 防止多个线程写入数据的顺序打乱

3.1.2实现多线程接收数据


class ChatServer(threading.Thread):

    def __init__(self, port):
        threading.Thread.__init__(self) 
        self.ADDR = ('', port) 
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 用于接收所有客户端发送信息的函数
    def tcp_connect(self, conn, addr):
    pass;

    # 每当接收到一个socket 连接就为其创建并启动一个新的线程
    def run(self):
        self.s.bind(self.ADDR)
        self.s.listen(5)
        print('服务器正在运行中...')
        q = threading.Thread(target=self.sendData)
        q.start()
        while True:
            conn, addr = self.s.accept()
            t = threading.Thread(target=self.tcp_connect, args=(conn, addr))
            t.start()
        self.s.close()


3.1.3处理接收到的数据

# 将接收到的信息(ip,端口以及发送的信息)存入que队列
def recv(self, data, addr):
    lock.acquire()
    try:
        que.put((addr, data))
    finally:
        lock.release()

# 用于接收所有客户端发送信息,并将数据保存到消息队列中
def tcp_connect(self, conn, addr):
    # 连接后将用户信息添加到users列表
    user = conn.recv(1024)                 # 接收用户名
    user = user.decode()

    for i in range(len(users)):
        if user == users[i][1]:
            print('User already exist')
            user = '' + user + '_2'

    if user == 'no':
        user = addr[0] + ':' + str(addr[1])
    users.append((conn, user, addr))
    print(' 新的连接:', addr, ':', user, end='')         # 打印用户名
    d = onlines()                  # 有新连接则刷新客户端的在线用户显示
    self.recv(d, addr)
    try:
        while True
评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值