我正在尝试从python客户端向服务器发送和接收C结构数据,反之亦然。客户端和服务器在连接和交换数据时都能顺利运行。客户端向服务器发送ctype结构,服务器再次将其发送回去。问题是我不知道如何解释客户端收到的消息,并以结构格式提取数据。我的最终想法是让python服务器和C-client相互通信并以预定义的结构交换数据。
以下是我在Python中为客户端和服务器提供的代码:
客户代码
import socket
import sys
import time
from ctypes import *
class payload_t(Structure):
_fields_ = [("ms", c_ulong),
("counter", c_ulong),
("DHT_temperature", c_float),
("DHT_humidity", c_float),
("DS_temperature", c_float),
("temperature_setpoint", c_float),
("time_setpoint", c_float)]
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port where the server is listening
server_address = ('localhost', 10000)
print >>sys.stderr, 'connecting to %s port %s' % server_address
sock.connect(server_address)
try:
for i in range(0,10):
# Send data
payload=payload_t(i*1000,i+1,25.2,45.7,25.8,33.22,3600.0)
message = payload
# 'This is the message. It will be repeated.'
print 'length of message %d' % sizeof(message)
print 'sending "', message.ms, message.counter, message.DHT_temperature, message.DHT_humidity, message.DS_temperature, message.temperature_setpoint, message.time_setpoint, '"'
sock.sendall(message)
# time.sleep(0.1)
# Look for the response
amount_received = 0
amount_expected = sizeof(message)
while amount_received < amount_expected:
datap = sock.recv(sizeof(message))
amount_received += len(datap)
print >>sys.stderr, 'received "%s"' % datap
print type(datap)
payload=payload_t()
datap.readinto(payload)
data=datap.readinto(payload_t)
data=struct.unpack(payload_t,datap)
print 'Received "', data.ms, data.counter, data.DHT_temperature, data.DHT_humidity, data.DS_temperature, data.temperature_setpoint, data.time_setpoint, '"'
finally:
print >>sys.stderr, 'closing socket'
sock.close()
服务器代码
import socket
import sys
from ctypes import *
class payload_t(Structure):
_fields_ = [("ms", c_ulong),
("counter", c_ulong),
("DHT_temperature", c_float),
("DHT_humidity", c_float),
("DS_temperature", c_float),
("temperature_setpoint", c_float),
("time_setpoint", c_float)]
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
server_address = ('localhost', 10000)
print >>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)
# Listen for incoming connections
sock.listen(1)
payload=payload_t(0,0,0.0,0.0,0.0,0.0,0.0)
while True:
# Wait for a connection
print >>sys.stderr, 'waiting for a connection'
connection, client_address = sock.accept()
try:
print >>sys.stderr, 'connection from', client_address
# Receive the data in small chunks and retransmit it
while True:
data = connection.recv(sizeof(payload))
print >>sys.stderr, 'received "%s"' % data
if data:
print >>sys.stderr, 'sending data back to the client'
connection.sendall(data)
else:
print >>sys.stderr, 'no more data from', client_address
break
finally:
# Clean up the connection
connection.close()
答案 0 :(得分:0)
首先,您正在转储收到的数据。您在每次循环迭代中重新分配变量'datap'。
做一些类似的事情:
datap += sock.recv(sizeof(message) - amount_received)
(当然,这不是最有效的代码,但你明白了。)
当您在'datap'var中组装结构时,可以使用'from_buffer'或'from_buffer_copy'方法将其加载到ctype类中。
payload = payload_t.from_buffer_copy(datap)
后者在您的情况下更好,因为重新绑定'datap'var时,您的缓冲区可能会消失。
答案 1 :(得分:-1)
如何通过调用recv_into提供ctypes.Structure的实例呢?
这是服务器代码的修改版本,希望我没有删除您要保留的功能
AddScoped
因此,基本上,我所做的唯一一件事就是使用socket.recv_in直接调用结构的实例: https://docs.python.org/3/library/socket.html#socket.recv_into
这使我以后可以直接访问结构属性。
我猜它的结构足够小(28个八位位组),这样数据就可以放在单个recv_into调用中。如果您需要多次调用recv_into来构建完整的结构,那么...
如果您使用python 3.7,则可以使用切片memoryviews对结构进行多次调用:
import socket
import sys
from ctypes import *
class payload_t(Structure):
_fields_ = [("ms", c_ulong),
("counter", c_ulong),
("DHT_temperature", c_float),
("DHT_humidity", c_float),
("DS_temperature", c_float),
("temperature_setpoint", c_float),
("time_setpoint", c_float)]
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
server_address = ('localhost', 10000)
print >>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)
# Listen for incoming connections
sock.listen(1)
payload=payload_t()
while True:
# Wait for a connection
print >>sys.stderr, 'waiting for a connection'
connection, client_address = sock.accept()
try:
print >>sys.stderr, 'connection from', client_address
# Receive the data in small chunks and retransmit it
while True:
data = connection.recv_into(payload)
print >>sys.stderr, 'received "%s"' % data
if data:
print >>sys.stderr, 'sending data back to the client'
print >>sys.stderr, 'time_setpoint "%f"' % payload.time_setpoint
connection.sendall(payload)
else:
print >>sys.stderr, 'no more data from', client_address
break
finally:
# Clean up the connection
connection.close()
没有任何东西可以保证诚实。使用早期版本的Python,尝试在memoryview上强制转换为“ B”时可能会出现异常。回想一下ctypes上的memoryview.Structure是0-dim,那么在没有强制转换的情况下将其切片几乎是不可能的...