zoukankan      html  css  js  c++  java
  • Python中自定义的实例通过网络进行传送

    Python中万物皆对象,假如我们需要在网络中传输数据,必须转换成二进制的格式。

    所以我们需要将具体的对象转换成字节码,然后通过socket进行网络输送。

    对于Python内置的字符串对象可以encode编码成字节码,全部的对象(包含字符串)可以通过pickle模块转换成字节码,对方收到消息直接反序列化就可以拿到对象。

    下面我通过简单的UDP协议进行数据传输试验:

    服务端文件:

    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    
    import socket
    import pickle
    
    MAX_BYTES = 65535
    
    def server(port):
        # 建立端口,设定ip传输协议以及端口协议
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # 绑定指定的ip与端口
        sock.bind(('127.0.0.1', port))
        print('Listening at {}'.format(sock.getsockname()))
        while True:
            # 接收信息
            data, address = sock.recvfrom(MAX_BYTES)
            # 解码
            text = pickle.loads(data)
            print('The client at {} says {!r}'.format(address, text))
            text = 'Your data was {} bytes long'.format(len(data))
            data = text.encode('ascii')
            # 发送信息
            sock.sendto(data, address)
    
    
    if __name__ == '__main__':
        server(1060)
    

      客户端文件

    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    
    import socket
    import pickle
    from datetime import datetime
    
    MAX_BYTES = 65535
    
    
    def client(port, data):
        # 建议端口
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        text = 'The time is {}'.format(datetime.now())
        print(text)
        data = pickle.dumps(data)
        # 发送消息
        sock.sendto(data, ('127.0.0.1', port))
        print('The OS assigned me the address {}'.format(sock.getsockname()))
        data, address = sock.recvfrom(MAX_BYTES)  # Danger! See Chapter 2
        text = data.decode('ascii')
        print('The server {} replied {!r}'.format(address, text))
    
    
    if __name__ == '__main__':
        for i in [range(5), list('abc'), dict(a=1,b=2)]:
            client(1060, i)
    

      

    执行 客户端

    (base) shijianzhongdeMacBook-Pro:chapter02 shijianzhong$ python client_host.py 

    The time is 2020-12-09 13:01:55.207264

    The OS assigned me the address ('0.0.0.0', 53972)

    The server ('127.0.0.1', 1060) replied 'Your data was 43 bytes long'

    The time is 2020-12-09 13:01:55.207624

    The OS assigned me the address ('0.0.0.0', 59785)

    The server ('127.0.0.1', 1060) replied 'Your data was 28 bytes long'

    The time is 2020-12-09 13:01:55.207813

    The OS assigned me the address ('0.0.0.0', 50027)

    The server ('127.0.0.1', 1060) replied 'Your data was 28 bytes long'

    服务端输出

    (base) shijianzhongdeMacBook-Pro:chapter02 shijianzhong$ python server_host.py 

    Listening at ('127.0.0.1', 1060)

    The client at ('127.0.0.1', 53972) says range(0, 5)

    The client at ('127.0.0.1', 59785) says ['a', 'b', 'c']

    The client at ('127.0.0.1', 50027) says {'a': 1, 'b': 2}

     可以实现通讯。

    当客户端传送给具体的Python对象给服务端时,服务端无法加载该对象。会报错

      File "server_host.py", line 28, in <module>

        server(1060)

      File "server_host.py", line 19, in server

        text = pickle.loads(data)

    AttributeError: Can't get attribute 'A' on <module '__main__' from 'server_host.py'>

    这个时候,需要对服务端进行进行一些调整,需要把原来的类传过来,并输入到该模块中

    服务端代码:

    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    
    import socket
    import pickle
    
    MAX_BYTES = 65535
    
    def server(port):
        # 建立端口,设定ip传输协议以及端口协议
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # 绑定指定的ip与端口
        sock.bind(('127.0.0.1', port))
        print('Listening at {}'.format(sock.getsockname()))
        while True:
            # 接收信息
            data, address = sock.recvfrom(MAX_BYTES)
            # 解码
            text = pickle.loads(data)
            if type(text) == str:
                #由于这是在函数里面运行,执行exec无法给模块赋值,所以绕了一圈
                g = {}
                # 执行赋值给g为
                exec(text, g)
                # 全局编码赋值此类
                globals()['A'] = g['A']
            else:
                print(text.name)
            print('The client at {} says {!r}'.format(address, text))
            text = 'Your data was {} bytes long'.format(len(data))
            data = text.encode('ascii')
            # 发送信息
            sock.sendto(data, address)
    
    
    if __name__ == '__main__':
        server(1060)
    

      客户端代码

    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    
    import socket
    import pickle
    from datetime import datetime
    import inspect
    
    MAX_BYTES = 65535
    
    
    class A:
        pass
    
    def client(port, data):
        # 建议端口
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        text = 'The time is {}'.format(datetime.now())
        print(text)
        data = pickle.dumps(data)
        # 发送消息
        sock.sendto(data, ('127.0.0.1', port))
        print('The OS assigned me the address {}'.format(sock.getsockname()))
        data, address = sock.recvfrom(MAX_BYTES)  # Danger! See Chapter 2
        text = data.decode('ascii')
        print('The server {} replied {!r}'.format(address, text))
    
    
    if __name__ == '__main__':
        content = inspect.getsource(A)
        a = A()
        a.name = 'sidian'
        client(1060, content)
        client(1060, a)
    

      执行后输出

    (base) shijianzhongdeMacBook-Pro:chapter02 shijianzhong$ python server_host.py 

    Listening at ('127.0.0.1', 1060)

    The client at ('127.0.0.1', 64398) says 'class A:     pass '

    sidian

    The client at ('127.0.0.1', 65487) says <A object at 0x7fb8158a1280>

    这里需要注意一下,类的定义要在__main__前面定义!

    通过此方法就可以将一个对象传递给另外一个Python脚本进程,实现自定义对象的传递。

    这里面主要用到了exec执行字符串命令的方式,给全局变量赋值该类为属性,那后续实例就可以直接通过pickle.loads读取了

     

    感觉还时很骚包的,一般应该用不到,哈哈哈哈

  • 相关阅读:
    java bio 之聊天室
    自定义gradle plugin
    gradle build 找不到tools.jar 解决方法
    java switch case 枚举类型的反编译结果
    spring mvc 关键接口 HandlerMapping HandlerAdapter
    H5 Video 去除 下载按钮 禁用右键
    https 请求发送 例子 tls && ssl
    mac 安装mongodb
    (扫盲)DTO数据传输对象
    (扫盲)RPC远程过程调用
  • 原文地址:https://www.cnblogs.com/sidianok/p/14108263.html
Copyright © 2011-2022 走看看