1. 程式人生 > >聊天室案例程式碼

聊天室案例程式碼

#註冊會員聊天
#聊天室伺服器
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()