聊天室案例代碼

#註冊會員聊天
#聊天室服務器
from socket import * 
import sys 
import os
import signal

def do_login(s,user,name,addr):
    for i in user:
        if i == name or 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
    return

def do_chat(s,user,tmp):
    #tmp = ['C','zhangsan','I','love','china']
    msg = '\n%-4s: %s'%\
    (tmp[1],' '.join(tmp[2:]))

    #給全部人轉發消息除了本身
    for i in user:
        if i != tmp[1]:
            s.sendto(msg.encode(),user[i])
    return

def do_quit(s,user,name):
    #從用戶字典刪除該用戶
    del user[name]

    msg = '\n' + name + '離開了聊天室'
    #講用戶退出的消息告知其餘用戶
    for i in user:
        s.sendto(msg.encode(),user[i])
    return

#接收處理
def do_child(s):
    #存儲用戶
    user = {}
    while True:
        #接收請求
        msg,addr = s.recvfrom(1024)
        msg = msg.decode()
        tmp = msg.split(' ')
        #L name
        if tmp[0] == 'L':
            do_login(s,user,tmp[1],addr)
        #C name text
        elif tmp[0] == 'C':
            do_chat(s,user,tmp)
        #Q name
        elif tmp[0] == 'Q':
            do_quit(s,user,tmp[1])

#發送系統消息
def do_parent(s,addr):
    name = 'C 管理員 '
    while True:
        msg = input("管理員消息:")
        msg = name + 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)
    #建立數據報套接字
    s = socket(AF_INET,SOCK_DGRAM)
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(ADDR)

    #處理殭屍進程
    signal.signal(signal.SIGCHLD,signal.SIG_IGN)

    #建立進程
    pid = os.fork()
    if pid < 0:
        print("create process failed")
        return
    elif pid == 0:
        do_child(s)
    else:
        do_parent(s,ADDR)

if __name__ == "__main__":
    main()
#管理員發言
#聊天室客戶端 
from socket import *
import sys 
import os 
import signal 

#發送請求,消息
def do_child(s,addr,name):
    while True:
        text = input('發言:')
        #表示用戶要退出聊天
        if text == 'quit':
            msg = 'Q ' + name 
            s.sendto(msg.encode(),addr)
            os.kill(os.getppid(),signal.SIGKILL)
            sys.exit(0)
        #正常聊天
        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發言:',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)
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)

    while True:
        name = input("請輸入姓名:")
        msg = 'L ' + name
        s.sendto(msg.encode(),ADDR)
        data,addr = s.recvfrom(1024) 
        if data.decode() == 'OK':
            break
        else:
            print("用戶名已存在")

    signal.signal(signal.SIGCHLD,signal.SIG_IGN)

    #建立進程
    pid = os.fork()
    if pid < 0:
        print("create process failed")
        return
    elif pid == 0:
        do_child(s,addr,name)
    else:
        do_parent(s)


if __name__ == "__main__":
    main()
相關文章
相關標籤/搜索