python qq聊天室

本文探讨了一个功能丰富的群聊聊天室系统,包括用户验证、消息推送、退出机制及管理员公告功能。技术点涉及数据流转、网络模型构建、用户信息管理及并发通信优化。通过实例代码展示了如何使用UDP、进程间通信和多线程实现这一功能。
摘要由CSDN通过智能技术生成

1. 群聊聊天室

功能: 类似QQ群功能

  1. 有人进入聊天室树要输入姓名,姓名不能重复
  2. 有人进入聊天室时,其他人会收到通知: xxx 进入聊天室
  3. 一个人发消息,其他人会收到: xxx: xxxxxx
  4. 有人退出聊天室,则其他人也会收到通知:xxx 推出了聊天室
  5. 扩展功能: 服务器可以向所有用户发送公告:管理员消息:xxxxx

2. 技术点的确定

  • 数据如何流转
    • 转发: 客户端>服务端>其他客户端
  • 网络模型如何构建
    • 构建UDP数据传输
  • 用户信息在哪维护怎么维护
    • 服务端:{name:address}或者[(name,address),]
  • 随意收发消息如何避免阻塞
    • 收发分别使用不同的进程执行

3. 结构设置注意事项

  • 采用什么封装结构: 函数
  • 编写一个功能测试一个功能
  • 注意注释和结构的设计

4.分析功能模块

  • 网络搭建
  • 进入聊天室
    • 客户端:
      • 输入姓名
      • 将请求发送给服务器
      • 接收结果
      • 允许则可以聊天,不允许则重新输入姓名
    • 服务单:
      • 接收请求
      • 判断 是否存在用户名
      • 如果允许进入则将用于存储,通知其他客户端
      • 如果不允许则结束
      • 将结果通知客户端
  • 聊天
    • 客户端:
      • 创建新的进程
      • 一个进程循环发送消息
      • 一个进程循环接收消息
    • 服务端
      • 接收请求
      • 判断请求类型
      • 将消息转发给其他人
  • 退出聊天室
    • 客户端
      • 输入quit或者ctrl-c退出
      • 将请求发送给服务端
      • 结束进程
    • 服务端
      • 接收请求
      • 将退出消息告知其他人
      • 给该用户发送exit
      • 删除用户
  • 管理员消息
    • 没有做

5.图解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pqcx3NOL-1639530767665)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211214192723554.png)]

6.通信协议设置

  • 进入聊天室: L
  • 聊天: C
  • 退出: Q
  • 服务器反馈: ok成功 其他表示失败
  • 客户端收到:exit 退出接收进程
  • 客户端输入:quit 直接退出

7. 服务端代码

"""
服务器端
"""
from socket import *
import time

# 服务器地址
ADDR = ('0.0.0.0', 18888)
OK = 'OK'
list_client = []


# 判断是否存在列表里面 如果不存在就加入列表
def is_exeit(name):
    global list_client
    for item, addr in list_client:
        if item == name:
            return False
    return True


def add_to_list(flag, name, addr):
    if flag:
        global list_client
        list_client.append((name, addr))


# 返回结果
def send_result(flag, addr, s):
    s.sendto(OK.encode(), addr) if flag else s.sendto("不允许".encode(), addr)


# 通知其他人
def send_all(flag, msg, s):
    if flag:
        global list_client
        for item, addr in list_client:
            s.sendto(msg.encode(), addr)


def do_quit(s, name):
    global list_client
    r_name, r_addr = ('', '')
    for item, addr in list_client:
        if item == name:
            r_name, r_addr = item, addr
            s.sendto('exit'.encode(), addr)
        else:
            s.sendto((name + ' 退出了').encode(), addr)
    list_client.remove((r_name, r_addr))


# 处理请求
def do_chat(s, name, msg):
    global list_client
    for item, addr in list_client:
        t_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        s.sendto(('%s %s:%s' % (t_str, name, msg)).encode(), addr)


# 登录
def do_login(addr, name, s):
    # 判断 是否 允许进入 如果允许进入
    flag = is_exeit(name)
    # 通知其他人
    send_all(flag, '欢迎"%s"进入聊天室' % name, s)
    # 存储结果
    add_to_list(flag, name, addr)
    # 返回结果
    send_result(flag, addr, s)


def do_request(s):
    global list_client
    # 循环收发消息
    while True:
        data, addr = s.recvfrom(1024)
        arr = data.decode().split(' ')
        state, name = arr[0], arr[1]
        if state == 'L':
            # 登录
            do_login(addr, name, s)
            print(list_client)
        elif state == 'C':
            # 群发
            msg = ' '.join(arr[2:])
            do_chat(s, name, msg)

        elif state == 'Q':
            do_quit(s, name)
            print(list_client)


# 搭建网络
if __name__ == '__main__':
    # udp服务端
    s = socket(AF_INET, SOCK_DGRAM)
    s.bind(ADDR)

    # 请求处理函数
    do_request(s)
    print('退出程序')

8.客户端代码

"""
    客户端
    发送请求,暂时结果
"""
import os
import sys

from socket import *
from multiprocessing import Process  # 导入模块
import time

# 服务器地址
ADDR = ('127.0.0.1', 18888)
OK = 'OK'


def recv_msg(s):
    while True:
        try:
            data, addr = s.recvfrom(4096)
            if data.decode() == 'exit':
                break
            print(data.decode())
        except:
            print('发送内容异常')
            break


def send_msg(s, name, addr, fn):
    sys.stdin = os.fdopen(fn)
    while True:
        try:
            data = input('')
            if data == "quit":
                msg = 'Q ' + name
                s.sendto(msg.encode(), addr)
                break
            msg = 'C %s %s' % (name, data)
            s.sendto(msg.encode(), addr)

        except:
            msg = 'Q ' + name
            s.sendto(msg.encode(), addr)
            print('输入内容异常')
            break


# 客户端启动函数
if __name__ == '__main__':


    fn = sys.stdin.fileno()
    s = socket(AF_INET, SOCK_DGRAM)
    # 进入聊天室
    while True:
        name = input("请输入姓名:")
        msg = 'L ' + name
        s.sendto(msg.encode(), ADDR)
        msg, addr = s.recvfrom(1024)
        if msg.decode() == OK:
            print('您已经进入聊天室')
            break

    # 创建进程 收发消息
    # 接收消息
    recv_process = Process(target=recv_msg,
                           name='recv_process', args=(s,))
    # 发送消息
    send_process = Process(target=send_msg,
                           name="send_process", args=(s, name, addr, fn))
    # 启动 接收消息进程
    recv_process.start()
    # 启动 发送消息进程
    send_process.start()
    # 等待进程结束
    try:
        recv_process.join()
        send_process.join()
        print('结束聊天')
    except:
        print('异常退出?')


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值