您的位置:首页 > 理论基础 > 计算机网络

基于数据包(UDP)的简易网络聊天室

2020-07-26 11:19 169 查看

    话不多说,直接上代码.

    服务器端:

    server.py

from socket import *
import os,sys
'''
聊天室文件
服务端
by:dyh
'''
###用户退出并且告知所有的用户###
def do_logout(s,user,name):
    #删除列表中的用户
    del user[name]
    msg='\n'+name+'离开了聊天室'
    for i in user:
        s.sendto(msg.encode(),addr)
    return
###用户登陆代码###
def do_login(s,user,name,addr):
    #用户注册时对用户name进行检查
    if (name in user) or name=='管理员':
        s.sendto('该用户已存在'.encode(),addr)
        return
    #用户name符合要求时发送OK给客户端提示其可以正常登陆
    #用户接收到信息以后对信息判断进行登陆操作
    s.sendto(b'OK',addr)
    msg='\n欢迎%s进入聊天室'%name
    #通知所有人
    for i in user:
        s.sendto(msg.encode(),user[i])
    #将用户插进字典
    user[name]=addr
    return

def do_chat(s,user,cmd):
    msg='\n%-4s:%s'%(cmd[1],' '.join(cmd[2:]))
    #将用户name发送给除了自己之外的所有人
    for i in user:
        if i!=cmd[1]:
            s.sendto(msg.encode(),user[i])
    return

#处理客户端请求
def do_child(s):
    #字典存储用户信息
    user={}
    #循环接收请求
    while True:
        msg,addr=s.recvfrom(1024)
        msg=msg.decode()
        cmd=msg.split('.')
        #根据不同请求做不同的事情
        if cmd[0]=='l':
            do_login(s,user,cmd[1],addr)
            s.sendto(b'OK',addr)
        elif cmd[0]=='m':
            do_chat(s,user,cmd)
        elif cmd[0]=='q':
            do_logout()
        else:
            s.sendto('请求错误'.encode(),addr)


#发送管理员消息
def do_parent(s,ADDR):
    while True:
        msg=input('管理员发消息:')
        msg='m.管理员'+msg
        s.sendto(msg.encode(),ADDR)
    s.close()
    sys.exit(0)

def main():
    if len(sys.argv)<3:
        print('argv error,')
        return
    HOST=sys.argv[1]
    PORT=int(sys.argv[2])
    ADDR=(HOST,PORT)

    #使用数据b报套接字
    s=socket(AF_INET,SOCK_DGRAM)
    #设置端口重用代码
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(ADDR)
    ###设置二级进程是为了将收消息和发消息分离###
    #创建一级子进程
    pid1=os.fork()

    if pid1<0:
        print()
    elif pid1==0:
        print('child process')
        pid2=os.fork()
        if pid2<0:
            print("")
        elif pid2==0:
            do_child(s)
        else:
            #一级子进程退出,使二级子进程成为孤儿
            os._exit(0)
    else:
        #等待一级子进程的退出
        os.wait()
        do_parent(s,ADDR)

if __name__=='__main__':
    main()

    客户端:

    client.py

from socket import *
import os,sys,signal
'''
聊天室文件
客户端
by:dyh
'''
#发送消息
def do_child(s,name,addr):
    while True:
        text=input("say:")
        if text=='quit':
            msg="q."+name
            s.sendto(msg.encode(),addr)
            #从子进程种杀掉父进程
            os.kill(os.getppid(),signal.SIGKILL)
            sys.exit('已退出!')
        else:
            msg='m.'+'%s.%s'%(name,text)
            s.sendto(msg.encode(),addr)
#收消息        
def do_parent(s):
    while True:
        msg,addr=s.recvfrom(1024)
        msg=msg.decode()
        msg=msg[:-1]
        print(msg+"\nsay:",end='')

def main():
    if len(sys.argv)<3:
        print('argv error,')
        return
    HOST=sys.argv[1]
    PORT=int(sys.argv[2])
    ADDR=(HOST,PORT)

    #使用数据报套接字
    s=socket(AF_INET,SOCK_DGRAM)
    ####登陆###
    while True:
        name=input("请输入姓名:")
        msg='l.'+name
        s.sendto(msg.encode(),ADDR)
        data,addr=s.recvfrom(1024)
        if data.decode()=='OK':
            print('###进入聊天室###')
            break
        else:
            print(data.decode())
    ###注意这里不要设置二级进程###
    #如果设置可能会在关闭客户端的时候杀死系统进程导致关机
    pid=os.fork()

    if pid<0:
        print(' ')
    elif pid==0:
        do_child(s,name,ADDR)
    else:
        #等待一级子进程的退出
        do_parent(s)

if __name__=='__main__':
    main()

 

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: