1. 程式人生 > >基於udp協議的群聊聊天室程式碼

基於udp協議的群聊聊天室程式碼

今天用python寫了一個簡單的群聊程式,分享一下

#server.py

from socket import *

import os,sys


def do_login(s,user,name,addr):
    if (name in user) or name == "管理員":
        s.sendto("該使用者已存在".encode(),addr)
        return
    s.sendto('ok'.encode(),addr)
    msg = '\n歡迎%s進入聊天室'%name
    for i in user:
        s.sendto(msg.encode(),user[i])
    #將使用者插入字典
    user[name] = addr   


def do_chat(s,user,name,text):
    msg = '\n%-4s 說:%s'%(name,text)
    #發給除了自己以外的所有人
    for i in user:
        if i != name:
            s.sendto(msg.encode(),user[i])


def do_quit(s,user,name):
    del user[name]
    msg = "\n" + name + '離開了聊天室'
    for i in user:
        s.sendto(msg.encode(),user[i])


#接受客戶端請求並處理
def do_child(s):
    #使用者儲存使用者{'zhangsan':('172,168,50,36',7777)}
    user = {}
    #迴圈接受各個客戶端請求並處理
    while True:
        msg,addr = s.recvfrom(1024)
        msglist = msg.decode().split(' ')
        #判斷請求型別進行處理
        if msglist[0] == 'L':
            do_login(s,user,msglist[1],addr)
        elif msglist[0] == 'C':
            do_chat(s,user,msglist[1],' '.join(msglist[2:]))
        else:
            do_quit(s,user,msglist[1])


#傳送管理員訊息
def do_parent(s,addr):
    while True:
        msg = input("管理員訊息:")
        msg = 'C 管理員 ' + msg
        s.sendto(msg.encode(),addr)




#建立套接字,建立連結,建立父子程序
def main():
    #server address
    ADDR = ("0.0.0.0",8888)
    s = socket(AF_INET,SOCK_DGRAM)
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(ADDR)


    #建立父子程序,並且防止殭屍程序
    pid = os.fork()


    if pid < 0:
        sys.exit("建立程序失敗")
    elif pid == 0:
        #建立二級子程序
        pid0 = os.fork()
        if pid0 < 0:
            sys.exit("建立二級程序失敗")
        elif pid0 == 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
import signal


#傳送訊息
def do_child(s,name,addr):
    while True:
        text = input("發言(quit退出):")
        if text.strip() == 'quit':
            msg = 'Q ' + name
            s.sendto(msg.encode(),addr)
            #從子程序中殺死父程序
            os.kill(os.getppid(),signal.SIGKILL)
            sys.exit("退出聊天室")
        else:
            msg = 'C %s %s'%(name,text)
            s.sendto(msg.encode(),addr)


#接受訊息
def do_parent(s):
    while True:
        msg,addr = s.recvfrom(1024)
        print(msg.decode()+"\n發言(quit退出):",end='')




#建立套接字,建立父子程序,登入
def main():
    if len(sys.argv) < 3:
        print("")
        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:
        sys.exit("建立程序失敗")
    elif pid == 0:
        do_child(s,name,ADDR)
    else:
        do_parent(s)


if __name__ == '__main__':
    main()