1. 程式人生 > 實用技巧 >Socket程式設計模擬初代QQ(自定義協議)Pycharm

Socket程式設計模擬初代QQ(自定義協議)Pycharm

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()