服务端:
""" /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()