udp协议与进程结合(群聊)

服务端:

"""
/etc/python3
@File     : chat_server.py
@Time     : 2020/7/13 下午5:15
@Author   : wangyongqi
@Email    : 92644827@qq.com
@SOftware : PyCharm
"""
from socket import *
from multiprocessing import Process

# 服务器使用地址
HOST = "0.0.0.0"
PORT = 8848
ADDR = (HOST,PORT)

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

# 处理进入聊天室
def do_login(sock,name,address):
    if name in user or '管理' in name:
        sock.sendto(b"FAIL",address)
        return
    else:
        sock.sendto(b"OK", address)
        # 通知其他人
        msg = "欢迎 %s 进入聊天室"%name
        for i in user:
            sock.sendto(msg.encode(),user[i])
        # 存储用户
        user[name] = address
        # print(user)

def get(sock,name,top):
        tmp='%s:%s'%(name,top)
        print(tmp)
        for i in user:
            if i!=name:
                sock.sendto(tmp.encode(),user[i])

def delect_exit(sock,name):
    del user[name]
    for i in user:
        sock.sendto(f'{name}退出了聊天'.encode(), user[i])


#将处理事件放在子进程,因为父进程要接收和处理管理员消息
def handle(sock):
    # 循环接收来自客户端请求
    while True:
        # 接收请求 (所有用户的所有请求)
        data, addr = sock.recvfrom(1024)
        tmp = data.decode().split(' ', 2)  # 对请求内容进行解析
        # 根据请求调用不同该函数处理
        if tmp[0] == 'L':
            # tmp ==> [L,name]
            do_login(sock, tmp[1], addr)  # 处理用户进入聊天具体事件
        #如果标记为C 则是消息进行转发
        elif tmp[0] == 'C':
            get(sock, tmp[1], tmp[2])
        #如果表记是e就是退出的表记
        elif tmp[0] == 'e':
            delect_exit(sock, tmp[1])


# 启动函数
def main():
    sock = socket(AF_INET,SOCK_DGRAM)  # UDP套接字
    sock.bind(ADDR)
    #设置消息处理的子进程
    p=Process(target=handle,args=(sock,))
    #子进程随着父进程的结束而退出<避免出现孤儿进程的情况>
    p.daemon=True
    #启动子进程
    p.start()
    #循环接收管理员消息(父进程的消息<输入的消息>)
    while True:
        conment=input("管理员:")
        #如果管理员输入exit也就是退出直接跳出循环结束父进程<子进程随之结束>
        if conment=='exit':
            break
        #若程序未跳出就将消息加标记 发给自己,然后处理转发给everyone
        data=f'c 管理员 {conment}'
        sock.sendto(data.encode(),ADDR)


if __name__ == '__main__':
    main()

客户端:

 

 

"""
/etc/python3
@File     : chat client.py
@Time     : 2020/7/13 下午5:15
@Author   : wangyongqi
@Email    : 92644827@qq.com
@SOftware : PyCharm
"""
from socket import *
from  multiprocessing import *

# 服务端地址
ADDR = ("127.0.0.1",8848)

# 请求进入聊天室 OK FAIL
def login(sock):
    while True:
        name = input("Name:")
        #加请求登录的表记L和用户名
        msg = "L " + name  # 根据通信协议整理发送信息
        print(name)
        #向服务器进行发送请求,服务器根据表记进行相应的处理
        sock.sendto(msg.encode(),ADDR) # 发送请求
        #等待服务器返回是否同意登录的应答
        result,addr = sock.recvfrom(128) # 等待回复
        #服务器返回OK说明登陆成功可以进行后续处理
        if result.decode() == 'OK':
            #主动给出提示
            print("您已进入聊天室")
            #返回用户名待用
            return name
        else:
            print("你的名字太受欢迎了,换一个吧")


#向服务器发送消息
def put(sock,name):
    while True:
        msg=input('说:')
        #判定消息如果退出结束父进程
        if msg=='exit':
            data = "e %s"%(name)
            sock.sendto(data.encode(), ADDR)  # 发送内容
            break
        #输入普通消息则加标记发送给服务器进行转发
        else:
            data = "C %s %s"%(name,msg) #C为普通消息
            sock.sendto(data.encode(),ADDR)  # 发送内容




def get(sock):
    while True:
        #阻塞等待服务器转发的消息
        data,addr = sock.recvfrom(1024) # 等待回复
        #打印消息
        print(data.decode())






def main():
    #创建用户套接字
    sock = socket(AF_INET,SOCK_DGRAM)
    #进入聊天室
    name=login(sock)
    #创建接收消息的子进程
    server_process = Process(target=get,args=(sock,))
    #父进程结束则结束子进程
    server_process.daemon=True
    #启动子进程
    server_process.start()
    #父进程发送消息
    put(sock, name)

if __name__ == '__main__':
    main()

 

posted @ 2020-07-14 20:11  爱吃萝卜爱吃兔  阅读(170)  评论(0编辑  收藏  举报