Python通过套接字发送和接收对象
我在网上搜索了很多,但是没有找到通过套接字发送对象并按原样接收的解决方案。我知道它需要酸洗,我已经做过了。将其转换为字节,然后从另一方面接收。但如何将这些字节转换为该类型的对象Python通过套接字发送和接收对象,python,sockets,Python,Sockets,我在网上搜索了很多,但是没有找到通过套接字发送对象并按原样接收的解决方案。我知道它需要酸洗,我已经做过了。将其转换为字节,然后从另一方面接收。但如何将这些字节转换为该类型的对象 process_time_data = (current_process_start_time, current_process_end_time) prepared_process_data = self.prepare_data_to_send(process_time_data)
process_time_data = (current_process_start_time, current_process_end_time)
prepared_process_data = self.prepare_data_to_send(process_time_data)
data_string = io.StringIO(prepared_process_data)
data_string = pack('>I' ,len(data_string)) + data_string
self.send_to_server(data_string)
这是在客户端将对象转换为StringIO并发送到服务器的代码。在服务器端,我得到字节。现在我正在搜索要再次转换为StringIO的字节,以便获得对象值
在代码中,对象被包装在StringIO中,并通过套接字发送。任何更好的方法都将受到高度赞赏
服务器端代码如下所示
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#server.setblocking(0)
server.bind(('127.0.0.1',50000))
server.listen(5)
inputs = [server]
outputs = []
message_queues = {}
while inputs:
readable, writeable, exceptional = select.select(inputs, outputs, inputs)
for s in readable:
if s is server:
connection, client_address = s.accept()
print(client_address)
connection.setblocking(0)
inputs.append(connection)
message_queues[connection] = queue.Queue()
print('server started...')
else:
print('Getting data step 1')
raw_msglen = s.recv(4)
msglen = unpack('>I',raw_msglen)[0]
final_data = b''
while len(final_data) < msglen:
data = s.recv(msglen - len(final_data))
if data:
#print(data)
final_data += data
message_queues[s].put(data)
if s not in outputs:
outputs.append(s)
else:
if s in outputs:
outputs.remove(s)
else:
break
inputs.remove(connection)
# s.close()
del message_queues[s]
process_data = ProcessData()
process_screen = ProcessScreen()
if final_data is not None:
try:
deserialized_data = final_data.decode("utf-8")
print(deserialized_data)
except (EOFError):
break
else:
print('final data is empty.')
print(process_data.project_id)
print(process_data.start_time)
print(process_data.end_time)
print(process_data.process_id)
这里要查找的是
加载
和转储
操作。套接字基本上是字节流。让我们考虑一下你的情况。
class ProcessData:
process_id = 0
project_id = 0
task_id = 0
start_time = 0
end_time = 0
user_id = 0
weekend_id = 0
需要通过执行data\u string=pickle.dumps(ProcessData())
将此类的实例pickle到数据字符串中,并通过执行data\u variable=pickle.loads(data)
取消pickle,其中data
是接收的内容
让我们考虑一个客户端创建一个对象的代码>进程数据< /COD>并将其发送到服务器。下面是客户的样子。这里有一个最小的例子
客户 现在,接收此数据的服务器如下所示def receive_all(server, message_length, message_queues, inputs, outputs):
# Helper function to recv message_length bytes or return None if EOF is hit
data = b''
while len(data) < message_length:
packet = server.recv(message_length - len(data))
if not packet:
return None
data += packet
message_queues[server].put(data)
if server not in outputs:
outputs.append(server)
else:
if server in outputs:
outputs.remove(server)
inputs.remove(server)
del message_queues[server]
return data
def receive_message(server, message_queues, inputs, outputs):
# Read message length and unpack it into an integer
raw_msglen = receive_all(server, 4, message_queues, inputs, outputs)
if not raw_msglen:
return None
message_length = unpack('>I', raw_msglen)[0]
return receive_all(server, message_length, message_queues, inputs, outputs)
class ProcessData:
process_id = 0
project_id = 0
task_id = 0
start_time = 0
end_time = 0
user_id = 0
weekend_id = 0
# Model class to send image data to the server
class ProcessScreen:
process_id = 0
image_data = bytearray()
服务器
运行服务器首先在端口上创建
绑定
,然后运行客户端
通过套接字进行数据传输。您还可以看看Pickle对于网络通信来说并不特别安全,因为它可以用来注入可执行代码。我建议您试试json
伪代码:
import json
to_send = json.dumps(object)
s.sendall (to_send)
一个选项是使用JSON序列化。 但是Python对象是不可序列化的,因此您必须首先使用函数
vars
(首选)或内置的\udict\udict
将类对象映射到Dict
根据以下内容调整答案:
客户
服务器
警告
重要的一点是,对象实例的dict映射不映射类变量
,只映射实例变量
。有关更多信息,请参见此。例如:
class ProcessData:
# class variables
process_id = 0
project_id = 1
def __init__(self):
# instance variables
self.task_id = 2
self.start_time = 3
obj = ProcessData()
dict_obj = vars(obj)
print(dict_obj)
# outputs: {'task_id': 2, 'start_time': 3}
# To access class variables:
dict_class_variables = vars(ProcessData)
print(dict_class_variables['process_id'])
# outputs: 0
请花些时间阅读帮助页面,特别是命名和的部分。更重要的是,请阅读。你可能还想了解一下。@Dharmindar“一旦我的老师说没有问题是不好的”——他们错了,肯定有不好的问题。这是其中之一。请参阅下面的建议副本,了解提问时需要哪些信息,以及对您有帮助的答案。正如@SudheeshSinganamalla所说,您的问题示例应该是最小的、完整的和可验证的。这不是一个完整的例子;它不是一个独立的代码块:也就是说,它不能按原样运行。如果没有相应的定义,我们所使用的变量和函数的唯一上下文就是它们的名称。这使得回答这个问题变得非常困难,更不用说充分了,这就是为什么它被否决的原因:投票的目的是根据优先级对问题进行分类。这可能是个坏问题,也可能不是个坏问题,但问得肯定不好。@Dharmindar你需要给我们更多的东西来合作。您可以编辑该问题,以解决我和其他在此发表评论的用户所表达的担忧:主要包括示例代码的其余部分(完整),减去与该问题无关的任何多余块(最小),以及我们可以解决的单个可重复问题(可验证)。否则,你不可能得到答案。你似乎在要求我远离的地方发表了评论。如果你编辑了这个问题,让它看起来像我发表评论时的样子,那么你会同时收到一个答案。我们之所以温和,是因为有经验的人可以回答你的问题,但当你的问题不清楚或占用太多时间时,没有人会花时间来回答。祝你好运你说你已经运行了,但它不工作是什么意思。您如何运行单个文件?您能否打开两个终端,将上述代码复制到相应的文件
server.py
和client.py
。在一个终端上运行服务器,在另一个终端上运行客户端。您将得到一个
作为响应,它是您从客户机发送到服务器的ProcessData
类的一个实例。@Dharmindar此示例非常有效,显示并解释了您需要完美完成的工作。这解决了您提出的问题,请将其标记为已接受。@Bilkokuya非常感谢@达曼达尔很高兴这有帮助。不过,我想告诉你一件事。你在上面的评论中提到了,而不是回应我的上一条评论,你可以回答这个问题,或者说这是我所不知道的。请理解,我们没有帮你一个忙,你不应该以这种方式与stackoverflow社区中的任何人交谈。祝你工作顺利。@SudheeshSinganamalla会记住这一点。再次感谢:)问题是因为限制了4096字节。您需要一个循环来接收所有数据,然后将4096
字节块连接到您想要的字符串中。这就是一个例子。您可以在stackoverflow上轻松搜索这些。请不要期望我们编写所有内容。类对象不是JSON可序列化的!
import json
to_send = json.dumps(object)
s.sendall (to_send)
import socket, json
class ProcessData:
process_id = 0
project_id = 0
task_id = 0
start_time = 0
end_time = 0
user_id = 0
weekend_id = 0
HOST = 'localhost'
PORT = 50007
# Create a socket connection.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
# Create an instance of ProcessData() to send to server.
variable = ProcessData()
# Map your object into dict
data_as_dict = vars(variable)
# Serialize your dict object
data_string = json.dumps(data_as_dict)
# Send this encoded object
s.send(data_string.encode(encoding="utf-8"))
s.close()
print 'Data Sent to Server'
import socket, json
class ProcessData:
process_id = 0
project_id = 0
task_id = 0
start_time = 0
end_time = 0
user_id = 0
weekend_id = 0
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
data_encoded = conn.recv(4096)
data_string = data_encoded.decode(encoding="utf-8")
data_variable = json.loads(data_string)
# data_variable is a dict representing your sent object
conn.close()
print 'Data received from client'
class ProcessData:
# class variables
process_id = 0
project_id = 1
def __init__(self):
# instance variables
self.task_id = 2
self.start_time = 3
obj = ProcessData()
dict_obj = vars(obj)
print(dict_obj)
# outputs: {'task_id': 2, 'start_time': 3}
# To access class variables:
dict_class_variables = vars(ProcessData)
print(dict_class_variables['process_id'])
# outputs: 0