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