聊天室

聊天室思路分析

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.将信息转发给所有登录的客户端        		
  * 退出聊天室  (输入##或者ctrl-c 表示退出)
   		客户端:输入退出标志
        	发送请求
        	进程结束
   		服务端: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'
   # 收到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)

# 存储用户信息 {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_exit(s,name):
# 防止用户不再user
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)
   # 判断请求类型 L   C    E
   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():
# 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)

if __name__ == '__main__':
main()
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值