• 基于Python的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()
     
     
     
  • 相关阅读:
    sqlserver备份后无法还原的解决方法
    Silverlight如何与JS相互调用
    【转】体验 Silverlight 5 3D开发之环境搭配篇
    C#实现邮箱搬家功能(1):Pop3协议介绍
    【转】针对大数据量表的优化查询
    Centos7Docker安装Redis
    Centos7.*Consul安装配置
    Centos7Docker安装nacos
    Centos7Docker安装neo4j
    Spring框架根据传入参数动态的修改注解属性的值
  • 原文地址:https://www.cnblogs.com/liam-sliversucks/p/13251980.html
Copyright © 2020-2023  润新知