Python学习-简易聊天室

聊天功能分析
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()

你可能感兴趣的:(Linux,Python学习,python,学习,开发语言)