聊天室思路分析
1. 需求分析 : 达到什么效果
2. 技术点分析
* 使用网络 : 数据报套接字
* 请求和响应模型: 客户端 --> 服务端 --> 数据处理
* 如何记录用户信息: {name:address}
[(name,address),...]
class Person:
def __init__(self,name,address):
self.name = name
self.address = address
* 多进程 : 一个进程控制发送
一个进程控制接收
3. 结构的设计和协议的设计
* 网络通信搭建
* 进入聊天室
* 聊天
* 退出聊天室
* 管理员消息
封装方法: 函数封装
协议设计:(两端通信就要涉及)
进入聊天室 : L name
反馈: 服务端发送 OK 其他的为失败
聊天 : C name content
退出 : E name
4. 逐个功能分析,列出逻辑流程
* 网络通信搭建
* 进入聊天室
客户端:1. 输入姓名
2. 发送请求
3. 接收结果 (成功,失败)
服务端:1. 接收请求 (请求类型区分)
2. 判断名字是否重复
3. 将结果返回给客户端
4. 如果允许进入 --》 告知其他客户端
* 聊天
客户端: 1.进程一:发送内容,收到发送成功的回复
2.进程二:接收信息
服务端: 1.收到客户端1/2/3的信息
2.将信息转发给所有登录的客户端
* 退出聊天室 (输入
客户端:输入退出标志
发送请求
进程结束
服务端:1.接收请求(请求类型区分)
2. 告知其他人
3. 将用户从user中删除
* 管理员消息
服务端:新进程
"""
chat room 客户端
* 发送请求,获取结果
"""
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 = '##'
if text == '##':
msg = 'E ' + 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(1024 * 1024)
except KeyboardInterrupt:
data = b'EXIT'
if data.decode() == 'EXIT':
sys.exit()
print(data.decode()+'\n头像:',end='')
def chat(s,name):
pid = os.fork()
if pid < 0:
os._exit(0)
elif pid == 0:
send_msg(s,name)
else:
recv_msg(s)
def main():
s = socket(AF_INET,SOCK_DGRAM)
while True:
name = input("请输入姓名:")
msg = "L " + name
s.sendto(msg.encode(),ADDR)
data,addr = s.recvfrom(1028)
if data.decode() == 'OK':
print("您已进入聊天室")
break
else:
print(data.decode())
chat(s,name)
if __name__ == '__main__':
main()
"""
chat room 服务端
env: python3.6
socket udp & fork
"""
from socket import *
import os, sys
ADDR = ('0.0.0.0', 8888)
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_exit(s,name):
if name not in user:
return
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(' ', 2)
if tmp[0] == 'L':
do_login(s, tmp[1], addr)
elif tmp[0] == 'C':
do_chat(s, tmp[1], tmp[2])
elif tmp[0] == 'E':
do_exit(s,tmp[1])
def main():
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)
if __name__ == '__main__':
main()