Socket程式設計模擬初代QQ(自定義協議)Pycharm
阿新 • • 發佈:2020-07-06
2020-07-05
需求說明:
1,轉發訊息
2,處理登入
3,處理退出
4,維護歷史訊息,維護線上使用者,維護線上使用者的連線
詳細細節:
1, 多執行緒去處理每個使用者連線,防止主執行緒阻塞
2,自定義了訊息協議,並且自己完成了訊息協議的解析
程式碼:
客戶端:
1 import socket 2 import json 3 import threading 4 5 client = socket.socket() 6 client.connect(("10.211.55.31", 8000)) 7 8 user = "Penguin1" 9 10 # 1,登入 11 login_template = {12 "action": "login", 13 "user": user 14 } 15 client.send(json.dumps(login_template).encode("utf8")) 16 res = client.recv(1024) 17 print(res.decode("utf8")) 18 19 # 2,獲取線上使用者 20 get_user_template = { 21 "action": "list_user", 22 } 23 client.send(json.dumps(get_user_template).encode("utf8")) 24 res = client.recv(1024) 25 print("當前線上使用者:{}".format(res.decode("utf8"))) 26 27 # 3,獲取歷史訊息 28 offonline_msg_template = { 29 "action": "history_msg", 30 "user": user 31 } 32 client.send(json.dumps(offonline_msg_template).encode("utf8")) 33 res = client.recv(1024) 34 print("歷史訊息:{}".format(res.decode("utf8"))) 35 36 exit = False 37 38 def handle_receive(): 39 # 處理接受請求 40 while True: 41 if not exit: 42 try: 43 res = client.recv(1024) 44 except: 45 break 46 res = res.decode("utf8") 47 try: 48 res_json = json.loads(res) 49 msg = res_json["data"] 50 from_user = res_json["from"] 51 print("收到來自({})使用者的訊息:{}".format(from_user, msg)) 52 except: 53 print(res) 54 else: 55 break 56 57 58 def handle_send(): 59 while True: 60 # 1,隨時傳送訊息 61 # 2,有訊息能夠隨時接收到 62 op_type = input("請輸入你要進行的操作:1,傳送訊息 2,退出 3,獲取當前線上使用者") 63 if op_type not in ["1", "2", "3"]: 64 print("不支援該操作") 65 op_type = input("請輸入你要進行的操作:1,傳送訊息 2,退出 3,獲取當前線上使用者") 66 elif op_type == "1": 67 to_user = input("請輸入你要傳送到使用者") 68 msg = input("請輸入你要傳送到訊息") 69 send_data_template = { 70 "action": "send_msg", 71 "to": to_user, 72 "from": user, 73 "date": msg, 74 } 75 client.send(json.dumps(send_data_template).encode("utf8")) 76 elif op_type == "2": 77 exit_template = { 78 "actino": "exit", 79 "user": user 80 } 81 client.send(json.dumps(exit_template).encode("utf8")) 82 exit = True 83 client.close() 84 break 85 elif op_type == "3": 86 get_user_template = { 87 "action": "list_user" 88 } 89 client.send(json.dumps(get_user_template).encode("utf8")) 90 91 92 if __name__ == "__main__": 93 send_thread = threading.Thread(target=handle_send) 94 send_thread.start() 95 receive_thread = threading.Thread(target=handle_receive()) 96 receive_thread.start()
伺服器:
1 import socket 2 from collections import defaultdict 3 import threading 4 import json 5 6 7 #1,維護使用者連線 8 online_users = defaultdict(dict) 9 #注意一定是傳的方法的名稱 10 11 # 2,維護使用者的歷史訊息 12 user_msgs = defaultdict(list) 13 14 server = socket.socket() 15 server.bind(("0.0.0.0", 8000)) 16 server.listen() 17 18 def handle_sock(sock, addr): 19 while True: 20 data = sock.recv(1024) 21 json_data = json.loads(data.decode("utf8")) 22 action = json_data.get("action", "") 23 if action == "login": 24 online_users[json_data["user"]] = sock 25 sock.send("登入成功".encode("utf8")) 26 elif action == "list_user": 27 #獲取當前線上使用者 28 all_users = [user for user, sock in online_users.items()] 29 sock.send(json.dumps(all_users).encode("utf8")) 30 elif action == "history_msg": 31 sock.send(json.dumps(user_msgs.get(json_data["user"], [])).encode("utf8")) 32 elif action == "send_msg": 33 if json_data["to"] in online_users: 34 online_users[json_data["to"]].send(json.dumps(json_data).encode("utf8")) 35 user_msgs[json_data["to"]].append(json_data) 36 elif action == "exit": 37 del online_users[json_data["user"]] 38 sock.send("退出成功!".encode("utf8")) 39 40 while True: 41 #阻塞等待連線 42 sock,addr = server.accept() 43 #啟動一個執行緒去處理新的使用者連線 44 client_thread = threading.Thread(target = handle_sock,args = (sock,addr)) 45 client_thread.start()