欢迎光临~扬州用友(畅捷通)软件--专业网络软件开发服务商-扬州七龙网络科技有限公司
  咨询电话:15952766660

python

网络聊天室练习(UDP)

服务器端

"""

群聊聊天室

功能:类似QQ群聊功能

1、有人进入聊天室需要输入姓名,姓名不能重复

2、有人进入聊天室时,其他人会收到通知:XXX进入聊天室

3、一个人发消息,其他人会收到:XXX:XXXXXXXXXXX

4、有人退出聊天室,则其他人也会收到通知:XXX退出了聊天室

5、扩展功能:服务器可以向所有用户发送公告:管理员消息:XXXXXXXXXXXXXXXXXX



思路分析:

1、技术点的确定

数据如何流动:转发-客户端-服务端-其他客户端

网络模型如何构建:构建UDP数据传输

用户信息在哪维护怎么维护:{name:address}   [(name,address),]

随意收发消息如何避免阻塞:收发分别不同的进程执行

2、结构设置注意事项

采用什么封装结构:函数

编写一个功能测试一个功能

注意注释和结构的设计

3、分析功能模块

网络搭建进入聊天室(客户端:输入姓名,将请求发送给服务,服务器允许进入则提示可以聊天,不允许则重新输入姓名。服务端:接收请求,判断是否存在用户名,

如果允许进入则将用户名存储,通知其他客户端,如果不允许进入,则结束。无论是否允许都将结果通知客户端)

-聊天(客户端:创建新的进程,一个进程玄幻发送消息,一个进程循环接受消息。服务端:接收请求,判断请求类型,将消息转发给其他人

)-退出聊天室-管理员发送消息

4、通信协议设置

进入聊天室:L

聊天:C

退出:Q

服务器反馈:OK成功   其他表示失败

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


    # 加入用户

    msg = "\n欢迎 %s 进入聊天室"%name

    for i in user:

        s.sendto(msg.encode(),user[i])

    user[name] = addr

    s.sendto(b'OK',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':

            if tmp[1] in user:

                do_quit(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) # 处理客户端请求


main()


客户端代码

"""

chat room 客户端

发送请求,展示结果

"""


from socket import *

import os,sys


# 服务器地址

ADDR = ('127.0.0.1',8888)


# 进入聊天室

def login(s):

    while True:

        try:

            name = input("请输入昵称:")

            if not name:

                continue

        except KeyboardInterrupt:

            sys.exit("谢谢使用")

        msg = "L " + name

        s.sendto(msg.encode(),ADDR)

        # 接收反馈结果

        data,addr = s.recvfrom(128)

        if data.decode() == 'OK':

            print("您已进入聊天室")

            return name

        else:

            print(data.decode())


# 子进程函数

def send_msg(s,name):

    while True:

        try:

            text = input("头像:")

        except KeyboardInterrupt:

            text = 'quit'

        # 退出聊天室

        if text.strip() == '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:

        data,addr = s.recvfrom(2048)

        # 接收进程退出

        if data.decode() == 'EXIT':

            sys.exit()

        print(data.decode()+'\n头像:',end='')


# 客户端启动函数

def main():

    s = socket(AF_INET,SOCK_DGRAM)

    name = login(s) # 请求进入聊天室


    # 创建新的进程

    pid = os.fork()

    if pid < 0:

        print("Error!!")

        return

    elif pid == 0:

        send_msg(s,name)  # 子进程发送消息

    else:

        recv_msg(s)  # 父进程接收消息


main()




上一条:并发编程 下一条:正则表达式

联系我们

QQ:274381

电 话:15952766660

微信:15952766660

邮 箱:webmaster@7hl.net

地 址:扬州市广陵区信息产业基地三号楼

用手机扫描二维码关闭
二维码