Python中使用Pi的对象传输

2024-03-28 10:47:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我有下面的类,一个点对象

class Point:
    def __init__(self):
        pass

    def __init__(self, x, y):
        self.x = x
        self.y = y

我有一个服务器(使用UDP)

^{pr2}$

我的客户端是:

import socket
import pickle
from Point import *

host = "localhost"
port = 10000
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

p = Point(10, 20)
a = pickle.dumps(p)

s.sendto(a, (host, port))

在服务器端,每当我得到p并打印它时,我会得到下面的(b'\x80\x03cPoint\nPoint\nq\x00)\x81q\x01}q\x02(X\x01\x00\x00\x00xq\x03K\nX\x01\x00\x00\x00yq\x04K\x14ub.', ('127.0.0.1', 55511))

我怎样才能得到这个物体,而不是这个?在


Tags: 对象importself服务器hostinitportdef
3条回答

泡菜不适合用于此目的。考虑this warning

Warning The pickle module is not secure against erroneous or maliciously constructed data. Never unpickle data received from an untrusted or unauthenticated source.

您的协议缺少任何类型的访问控制,因此您的进程容易受到任意远程代码执行攻击。在

考虑一个真正的网络协议。有许多可供选择的。例如,Cap' Proto。在

解决方案是在服务器端使用pickle.loads,如下所示

d = s.recvfrom(1024)
p1 = Point(1,1)
p1 = pickle.loads(d[0])
print(str(p1.x))

然而,正如许多人所说,pickle可能不是这种情况下的最佳解决方案。在

首先,一个警告。pickle允许执行任意代码。不要使用这个来接受任意连接,最好使用加密来确保您只交换可信的数据。即使这样,也可以考虑使用更安全的交换格式。在

接下来,考虑UDP数据包的大小是有限的。您需要确保pickle数据足够小,能够容纳UDP数据包(最大有效负载大小为65507字节)。至少当你收到包裹时,你会知道你有所有的数据。使用65535作为缓冲区大小,以确保可以完全接收大数据包。在

发送时,请确保不要超过大小限制:

MAX_UDP_SIZE = 65507  # https://en.wikipedia.org/wiki/User_Datagram_Protocol

a = pickle.dumps(p)
if len(a) > MAX_UDP_SIZE:
    raise ValueError('Message too large')
s.sendto(a, (host, port))

另一方面,使用^{}将pickle数据流转换回一个对象:

^{pr2}$

我强烈建议您至少验证addr是可信的,否则您可以随意执行任意代码。65507字节有足够的空间发送pickle来控制进程。在

如果您需要发送更多数据,那么您将需要使用TCP而不是UDP,因为您必须按照特定的顺序跨数据发送,分布在多个数据包中,并且需要所有数据包都到达接收端;TCP提供了这一层的可靠性。在这一点上,您必须在pickle前面加上一个固定数量的字节,编码pickle的大小,这样就可以确保在另一端再次读取相同数量的数据。在

相关问题 更多 >