+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2020-03(70)

2020-04(60)

2020-05(24)

2020-06(39)

2020-07(23)

群聊天室

发布于2019-12-07 16:47     阅读(734)     评论(0)     点赞(9)     收藏(0)


0

1

2

3

4

5

6

7

群聊聊天室

功能 : 类似qq群功能
【1】 有人进入聊天室需要输入姓名,姓名不能重复
【2】 有人进入聊天室时,其他人会收到通知:xxx 进入了聊天室
【3】 一个人发消息,其他人会收到:xxx : xxxxxxxxxxx
【4】 有人退出聊天室,则其他人也会收到通知:xxx退出了聊天室
【5】 扩展功能:服务器可以向所有用户发送公告:管理员消息: xxxxxxxxx

聊天室思路分析

  1. 需求的整理 : 达到什么效果,如何工作

  2. 技术点的分析

    • 通信套接字
      udp通信

    • 数据流方向

      c --> s
      客户端 请求 —> 服务端处理
      信息 客户端–》 服务端 -->其他客户端

    • 服务端需要存储用户什么信息,怎么存
      用户名 地址
      [(name,address),(name,address)…]
      {name:address,}
      class Person:
      def init(self,name,address):
      self.name = name
      self.address = address

    • 收发消息
      收消息和发消息使用不同的进程

  3. 结构设计和协议的设定

    • 网络结构搭建
    • 进入聊天室
    • 聊天
    • 退出聊天室功能
    • 管理员消息
      封装结构: 函数
      请求协议: L name
      C text…
      Q name
      响应协议: OK FAIL
  4. 逐个功能分析,罗列逻辑流程

    • 网络结构搭建
      udp网络

    • 进入聊天室
      客户端: 输入姓名
      发送登录请求
      得到登录结果
      服务端: 接收请求
      判断用户是否可以登录
      向客户端回复结果
      如果该客户端登录了则告知其他人

    • 聊天
      客户端: 创建新的进程
      一个进程循环的接收消息
      一个进程循环输入内容发送

      服务端: 接收消息 C name xxxxx
      转发给其他人 “name: xxxxxx”

    • 退出聊天室功能
      客户端 quit ctrl-c 退出
      发送请求给服务端
      结束进程

      服务端 接收请求
      删除该用户
      告知其他人

    • 管理员消息

客户端代码

"""
chat room  AID 1910
env: python3.6
author:姚高宽
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(b'FAIL',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_quit(s,name):
    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)
        # 根据请求类型,选择功能模块去处理
        # L   C   Q
        if tmp[0] == 'L':
            do_login(s,tmp[1],addr) # 具体函数处理具体功能
        elif tmp[0] == 'C':
            do_chat(s,tmp[1],tmp[2])
        elif tmp[0] == 'Q':
            do_quit(s,tmp[1])

# 启动函数
def main():
    # udp网络服务
    s = socket(AF_INET,SOCK_DGRAM)
    s.bind(ADDR)

    pid = os.fork()
    if pid < 0:
        return
    elif pid == 0:
        # 管理员消息的发送
        while True:
            text = input("管理员消息:")
            msg = "C 管理员 "+text
            # 将消息从子进程发送给父进程
            s.sendto(msg.encode(),ADDR)
    else:
        do_request(s) # 父进程处理请求


if __name__ == '__main__':
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

服务端代码呈现

"""
chat room client
"""
from socket import *
import os,sys

# 服务器地址
ADDR = ('127.0.0.1',8888)

# 发送消息
def send_msg(s,name):
    while True:
        try:
            text = input("Msg>>")
        except KeyboardInterrupt:
            text = 'quit'
        # 退出
        if text == 'quit':
            msg = "Q "+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(4096)
        except KeyboardInterrupt:
            sys.exit()
        if data == b'EXIT':
            sys.exit()
        print(data.decode()+'\nMsg>>',end='')

# 客户端启动函数
def main():
    s = socket(AF_INET,SOCK_DGRAM)
    # 进入聊天室部分
    while True:
        name = input("请输入姓名:")
        msg = "L "+name
        s.sendto(msg.encode(),ADDR)
        # 得到结果
        data,addr = s.recvfrom(128)
        if data.decode() == 'OK':
            print("您已进入聊天室")
            break
        else:
            print('进入聊天室失败')

    pid = os.fork()
    if pid < 0:
        return
    elif pid == 0:
        send_msg(s,name) # 子进程发送
    else:
        recv_msg(s) # 父进程接收


if __name__ == '__main__':
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

0

1

2

3

4

5

6



所属网站分类: 技术文章 > 博客

作者:9384vfnv

链接: https://www.pythonheidong.com/blog/article/170131/13f439b2d3d796a2646c/

来源: python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

9 0
收藏该文
已收藏

评论内容:(最多支持255个字符)