当前位置 博文首页 > python实现简易聊天室(Linux终端)

    python实现简易聊天室(Linux终端)

    作者:mianmabb 时间:2021-08-02 18:15

    本文实例为大家分享了python实现简易聊天室的具体代码,供大家参考,具体内容如下

    群聊聊天室

    1.功能:类似qq群聊功能

    1.有人进入聊天室需要输入姓名,姓名不能重复

    2.有人进入聊天室,其他人会受到通知
    xxx进入聊天室

    3.一个人发消息,其他人会受到消息
    xxx:xxxxxxxx

    4.有人退出聊天室,其他人也会收到通知
    xxx退出聊天室

    5.扩展功能:服务端消息公告,服务端发送消息所有人都能收到
    管理员消息:xxxxxxxx

    2.确定技术模型

    1.服务端和客户端

    服务端处理请求,发送管理员消息
    客户端执行各种功能

    2.套接字选择:udp套接字

    3.消息发送模型:转发
    客户端 ~> 服务端 ~> 其他客户端

    4.存储用户信息:{name:addr}

    5.处理收发关系:多进程分别处理收发

    3.注意事项

    1.设计封装方案

    2.写一个功能模块测试一个模块

    3.注意注释的添加

    #coding =utf-8
    '''
    chat room
    env:python3.5
    exc:socket and fork
    name:mianmabb
    email:mianmabb@163.com
    服务端功能:
    1.搭建网络通信
    2.处理进入聊天室
        * 接收姓名
        * 判断是否允许进入
        * 将结果反馈给客户端
        * 如果不允许则结束,允许则将用户插入数据结构
        * 给其他人发送通知
    3.处理聊天
        * 接收消息,判断消息类型,分为L(输入姓名),C(发消息),Q(退出聊天室)
        * 将消息转发
    4.处理退出聊天室
    5.发送管理员消息 
    '''
    
    from socket import *
    from os import *
    from sys import *
    
    user = {}   #创建空字典用来存储用户的昵称和地址
    
    #处理登录
    def do_login(s,name,addr):
        if name in user:    #判断昵称是否已经存在
            s.sendto('该昵称已被占用'.encode(),addr)
            return
        else:    #昵称不存在,则发送约定好的'OK'
            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 = '%s : %s'%(name,text)   #设置消息显示格式
        for i in user:
            s.sendto(msg.encode(),user[i])
    
    #处理退出
    def do_quit(s,name):
        msg = '%s 退出了聊天室'%name
        for i in user:
            if i != name:   #给其他人发送该用户退出的消息
                s.sendto(msg.encode(),user[i])
            else:   #给该用户客户端发送约定好的EXIT让父进程退出
                s.sendto(b'EXIT',user[i])
        del user[name]   #删除字典中该用户
    
    
    #处理请求
    def do_request(s):
        #循环接受所有客户请求
        while True:
            try:
                data,addr = s.recvfrom(1024)
            except KeyboardInterrupt:    #捕获父进程直接退出错误
                exit('服务端退出!')
    
            # print(data.decode())
            msgList = data.decode().split()   #按空格拆分为列表,方便索引
    
            if msgList[0] == 'L':    #判断消息类型
                do_login(s,msgList[1],addr)
    
            elif msgList[0] == 'C':
                text = ' '.join(msgList[2:])  #将消息中可能有的空格加回来
                do_chat(s,msgList[1],text)
            elif msgList[0] == 'Q':
                do_quit(s,msgList[1])
    
    
    
    def main():
        s = socket(AF_INET,SOCK_DGRAM)
        ADDR = ('0.0.0.0',8888)
        s.bind(ADDR)
    
        #创建进程
        pid = fork()
        if pid < 0:
            print('Error')
        elif pid == 0:   #子进程用来发送管理员消息
            while True:
                try:
                    text = input('管理员 : ')
                except KeyboardInterrupt:    #捕获子进程直接退出错误
                    exit()
    
                msg ='C 管理员 %s'%text
                s.sendto(msg.encode(),ADDR)
    
        else:   #父进程用来处理请求
            do_request(s)
    
    
    
    main()

    客户端功能:

    '''
    1.搭建通信
    2.进入聊天室
        * 输入姓名
        * 发送给服务器
        * 接收服务器反馈
        * 不允许则重新输入,允许则进入聊天室
        * 创建新的进程用于消息收发
    3.聊天
        * 循环发送消息  消息类型分为L(输入姓名),C(发消息),Q(退出聊天室)
        * 循环接收消息
    4.退出聊天室
    5.接受管理员消息
    '''
    
    
    from socket import *
    from os import *
    from sys import *
    
    ADDR = ('127.0.0.1',8888)    #填写服务端地址
    
    #循环发送消息
    def send_msg(s,name):
        while True:
            try:
                text = input()   #客户输入要发送的消息
            except KeyboardInterrupt:   #子进程 防止用户Ctrl+C直接退出
                text = 'quit'
    
            if text.strip() == 'quit':    #规定输入quit退出
                msg = 'Q ' + name     #消息类型,姓名
                s.sendto(msg.encode(),ADDR)
                exit('您已退出聊天室')
            else:
                msg = 'C %s %s'%(name,text)  #消息类型,姓名,消息
                s.sendto(msg.encode(),ADDR)
    
    #循环接收信息
    def recv_msg(s):
        while True:
            try:
                data,addr = s.recvfrom(1024)
            except KeyboardInterrupt:    #父进程 防止用户Ctrl+C直接退出
                exit()
            if data.decode() =='EXIT':   #当用户退出,无需再收消息,约定EXIT让父进程退出
                exit()   #退出父进程
    
            print(data.decode())
    
    
    #创建网络连接
    def main():
        s = socket(AF_INET,SOCK_DGRAM)
        while True:
            name = input('请输入昵称:')     #输入姓名
            if not name:
                return
            msg = 'L ' +name
            #发送请求
            s.sendto(msg.encode(),ADDR)
            #等待回复
            data,addr = s.recvfrom(1024)
            if data.decode() == 'OK':
                print('您已进入聊天室')
                break
            else:   #登录失败
                print(data.decode())  #直接打印服务端的错误信息
            
        #创建进程
        pid = fork()
        if pid < 0:
            print('Error')
        elif pid == 0:   #子进程发消息
            send_msg(s,name)
        else:      #父进程收消息
            recv_msg(s)
    
    
    main()

    先运行服务端,再运行客户端

    jsjbwy
    下一篇:没有了