Python学习-简易聊天室

2023-09-21 17:04:22
聊天功能分析
1.网络搭建
2.进入聊天室
    客户端:
        1.输入姓名
        2.将请求发送给服务器
        3.接收结果,允许进入则可以聊天,不允许则重新输入姓名
    服务器:
        1.接收请求
        2.判断姓名是否存在,如果允许进入,存储用户基本信息,通知其他客户端,如不允许则结束
        3.将结果通知客户端
3.聊天
    客户端
        1.创建新的进程
        2.一个进程循环接收消息
        3.一个进程循环接收消息
    服务器
        1.接收请求
        2.判断请求类型
        3.将消息转发给其他人
4.退出聊天
    客户端
        输入quit或者ctrl+c退出
        将请求发送服务器
        结束进程
    服务器
        接收请求
        将退出消息告知其他人
        给该用户发送EXIT
        删除用户
5.管理员消息
6.通信协议设置
    进入聊天室:L
    聊天:C
    退出:Q
    服务器反馈:OK表示成功,其它表示失败
    客户端收到    EXIT     退出接收进程
聊天代码
聊天服务器端代码
"""
聊天室
env: python3.10
socket udp & fork
"""

from socket import *
import os, sys

"""
全局变量:被多个模块使用或有一定固定含义
"""
# 服务器地址
ADDR = ('0.0.0.0', 8888)

# 存储用户 {name:address}
user = {}


def do_login(s, name, addr):
    if name in user  or "管理员" in name:
        s.sendto("该用户存在".encode(), addr)
        return
    s.sendto(b'OK', addr)  # 可以进入聊天室
    # 通知其他人
    msg = "\n欢迎'%s'进入聊天室" % name
    for i in user:
        s.sendto(msg.encode(), user[i])
    # 将用户插入字典
    user[name] = addr


# 聊天
def do_chat(s, name, text):
    msg = "\n%s : %s " %(name, text)
    for i in user:
        # 刨除本人
        if i != name:
            s.sendto(msg.encode(), user[i])


# 退出
def do_quit(s, name):
    msg = "\n%s 退出聊天室" %name
    for i in user:
        if  i!= name:
            s.sendto(msg.encode(), user[i])
        else:
            s.sendto(b'EXIT', user[i])
    del user[name]           # 删除用户


# 封装请求处理函数
def do_request(s):
    while True:
        data, addr = s.recvfrom(1024)
        tmp = data.decode().split(' ')  # 请求拆分
        #  根据不同请求类型具体执行不同的事情(L 进入,C 聊天,Q 退出)
        if tmp[0] == 'L':
            # 执行具体工作
            do_login(s, tmp[1], addr)
        elif tmp[0] == 'C':
            text = ' '.join(tmp[2:])
            do_chat(s, tmp[1], text)
        elif tmp[0] == "Q":
            do_quit(s, tmp[1])
        print(data.decode())


# 搭建网络
def main():
    # udp服务器
    s = socket(AF_INET, SOCK_DGRAM)
    s.bind(ADDR)
    pid = os.fork()
    if pid == 0:
        while True:
            msg = input("管理员消息:")
            msg = "C 管理员 " + msg
            s.sendto(msg.encode(), ADDR)
    else:
        # 请求处理函数
        do_request(s)


main()

聊天客户端代码
"""
聊天室 客户端
发送请求,展示结果
"""

from socket import *
import os,  sys
# 服务器地址
ADDR = ('127.0.0.1', 8888)


# 发送消息
def send_msg(s, name):
    while True:
        try:
            text = input("发言:")
        except KeyboardInterrupt:
            text = 'quit'
        if text.strip() == "quit":
            msg = "Q " + name
            s.sendto(msg.encode(), ADDR)
            sys.exit("退出聊天室")
        msg = "C %s %s" %(name, text)
        s.sendto(msg.encode(), ADDR)


# 接收消息
def recv_msg(s):
    while True:
        try:
            data, addr = s.recvfrom(4096)
        except KeyboardInterrupt:
            sys.exit()
        # 从服务器收到EXIT退出
        if data.decode() == "EXIT":
            sys.exit()
        print(data.decode())


# 客户端启动函数
def main():
    s = socket(AF_INET, SOCK_DGRAM)

    # 进入聊天室
    while True:
        name = input("请输入姓名:")
        msg = 'L ' + name
        s.sendto(msg.encode(), ADDR)
        # 接收反馈
        data, addr = s.recvfrom(128)
        if data.decode() == "OK":
            print("您已进入聊天室")
            # break
        else:
            print(data.decode()+"\n发言:", end='')

        pid = os.fork()
        if pid < 0:
            sys.exit("Error!")
        elif pid == 0:
            send_msg(s, name)        # 子进程负责消息发送
        else:
            recv_msg(s)          # 父进程负责消息接收


main()
更多推荐

难得有个冷静的程序员发言了:纯编码开发实施的项目,失败的案例也有很多

难得有个冷静的程序员发言了:纯编码开发实施的项目,失败的案例也有很多。假如用低代码实施,能达到不失败或提高成功率,对软件开发项目交付,会是重大的价值。我的观点:两者都可能失败,不同的是,传统编程开发的项目,失败都是发生在项目的中后期,前期靠PPT保证,在实施过程中,做着做着就发现做不下去了(需求风险,成本风险,技术风险

硬件故障诊断:快速定位问题

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🦄博客首页——🐅🐾猫头虎的博客🎐🐳《面试题大全专栏》🦕文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》🐾学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》🐅学会Gol

Golang数组和slice

Golang数组和Slice(切片)Go语言中数组长度固定不可变动,slice则可以增长缩短(使用较多)一、数组类型Go语言中数组长度固定,索引从0开始计数。需要注意数组的长度一开始必须是固定的,且不同长度的数组其表示不同的数据类型,相同的数组可以进行‘==’比较。数组作为函数参数是使用的是形参的方式,函数内不可改变其

Tokenview X-ray功能:深入探索EVM系列浏览器的全新视角

Tokenview作为一家领先的多链区块浏览器,为了进一步优化区块链用户的使用体验,我们推出了X-ray(余额透视)功能。该功能将帮助您深入了解EVM系列浏览器上每个地址的交易过程,以一种直观、简洁的方式呈现地址的进出账情况,让您轻松掌握资产流转。X-ray功能特性1多级合约调用的直观展示在区块链世界中,资产流转是一个

第七章(1):深度神经网络的基本结构、训练方法和在机器学习中的重要性

第七章(1):深度神经网络的基本结构、训练方法和在机器学习中的重要性作者:安静到无声个人主页作者简介:人工智能和硬件设计博士生、CSDN与阿里云开发者博客专家,多项比赛获奖者,发表SCI论文多篇。Thanks♪(・ω・)ノ如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!o( ̄▽ ̄)d欢迎大家来到

GDAL库学习

GDAL库学习GDAL是一个操作栅格数据和矢量数据的库,对图像而言,可以进行包括读取、写入、转换、处理各种操作。文章目录GDAL库学习RasterIO()函数1.添加引用2.读取图像3.获取图像基本信息4.保存输出图像5.释放RasterIO()函数RasterIO(GDALRWFlageRWFlag,intnXOff

全网最全知识图谱讲解!

什么是知识图谱知识图谱标准化白皮书定义:知识图谱(KnowledgeGraph)以结构化的形式描述客观世界中概念、实体及其关系,将互联网的信息表达成更接近人类认知世界的形式,提供了一种更好地组织、管理和理解互联网海量信息的能力。简单讲,知识图谱由节点(point)和边(edge)组成,每个节点表示一个实体,实体可以指客

DC电源模块宽电压输入和输出的范围是多少?

BOSHIDADC电源模块宽电压输入和输出的范围是多少?直流电源模块是一种常用的电源设备,可以将交流电转换成稳定的直流电,被广泛应用于各种工业自动化、数字电子、通信设备等领域。在实际使用中,用户需要了解直流电源模块的工作电压范围,以便正确选择和使用。直流电源模块的输入电压范围通常被称为宽电压输入,是指该模块可以接受的输

全栈性能测试工具:RunnerGo

随着自动化测试技术的不断进步,自动化测试已成为企业级应用的重要组成部分。然而,传统的性能测试工具往往复杂、繁琐,让企业陷入了两难的境地。软件测试正逐渐从手动测试向自动化测试转变,各种自动化测试工具和框架层出不穷,极大地提高了测试效率和质量。近年来出现的敏捷开发方法使得软件测试需要更快地跟进开发节奏,不断适应变化。敏捷测

2023年全网最全的软件测试八股文,稳进大厂(含答案)

Part11、你的测试职业发展是什么?测试经验越多,测试能力越高。所以我的职业发展是需要时间积累的,一步步向着高级测试工程师奔去。而且我也有初步的职业规划,前3年积累测试经验,按如何做好测试工程师的要点去要求自己,不断更新自己改正自己,做好测试任务。优势在于我对测试坚定不移的信心和热情,虽然经验还不够,但测试需要的基本

ModStartCMS v7.3.0 富文本MP3支持,后台组件优化

ModStart是一个基于Laravel模块化极速开发框架。模块市场拥有丰富的功能应用,支持后台一键快速安装,让开发者能快的实现业务功能开发。系统完全开源,基于Apache2.0开源协议,免费且不限制商业使用。功能特性丰富的模块市场,后台一键快速安装会员模块通用且完整,支持完整的API调用大文件分片上传,进度条显示,已

热文推荐