Python 套接字:无法接收 int 数组
Python socket: cannot receive int array
我尝试通过 winsockets 在 Python 和 c 程序之间进行进程间通信。发送一个字符串确实有效,但现在我尝试将一个 int 数组从 c 套接字发送到 python 套接字。
我已经发现我必须使用 htonl() 将 int 数组转换为字节流,因为 winsock2 的发送函数不能直接发送 int 数组。
现在我想在 python 套接字中使用 ntohl() 但接收函数 returns 字节,而 ntohl() 需要一个整数值作为输入。
这是我的代码
C端(仅相关部分):
uint32_t a[1] = {1231};
uint32_t a_converted[1]={0};
a_converted[0] = htonl(a[0]);
iResult = send( ConnectSocket, ( char *) a_converted, sizeof( a_converted), 0 );
Python 边(仅相关部分):
data = connection.recv(16)
data_i = socket.ntohl(data)
您说您已成功通过连接发送字符串。我假设您发送了一个 char*
并在 python 中收到了它作为一个字符串。你所做的是发送一个字节流。
现在您想发送一个整数数组。在内存中,整数再次存储为字节。
每个整数可能占用 4/8 字节。您可以通过打印
来事先检查
printf("Size of integer is %zu", sizeof(int));
好的,很好,现在我们知道需要发送多少字节了。假设现在是 4。
我们还需要知道整数的字节序,但我们现在假设是大字节序。
这意味着最低有效字节在前,最高有效字节在最后。
所以现在您可以发送整数数组,方法是将数组转换为 char*
并发送 sizeof(array)
.
虽然在接收端,您只有一个字节流。要将其转换为整数数组,您需要一次获取 4 个字节并将其组合成一个整数。
我们可以这样做。
假设共有 10 个整数。您必须以某种方式单独传递此信息。
bytes = connection.recv(10*4)
array = []
for i in range(10):
x = ord(bytes[i*4+0])
x += ord(bytes[i*4+1]) << 8
x += ord(bytes[i*4+2]) << 16
x += ord(bytes[i*4+3]) << 24
array += [x]
print x
您将能够看到整数数组。
此处函数 ord
将一个字符转换为其 ASCII 等效整数。
旁注:
现在,如果您的系统的整数大小为 8 而不是 4,则您需要扩展 python 中的循环体。它将一直持续到 56。此外,每个索引(以字节为单位)将是 i*8+...
同样,如果字节顺序不同,元素的顺序也会改变。基本上 bytes
上的索引将从 i*4+3
变为 i*4+0
。
你收到的是一串字节,ntohl没有异常吗?
您可以使用 struct 模块解压 - 16 字节
struct.unpack('!4I', data)
含义 - 按网络顺序解压 4 个无符号 32 位整数
(我无法测试,请自行尝试)
编辑:
哎呀,没看完你的评论。根据 sockets docs,recv 应该 return 类型为 bytes 的对象。如果它 returns 类型为 str 的对象 - 您应该将其转换为 bytes - 在 Python3 中它将是 data.encode()
PS你在哪个Python?
我尝试通过 winsockets 在 Python 和 c 程序之间进行进程间通信。发送一个字符串确实有效,但现在我尝试将一个 int 数组从 c 套接字发送到 python 套接字。
我已经发现我必须使用 htonl() 将 int 数组转换为字节流,因为 winsock2 的发送函数不能直接发送 int 数组。
现在我想在 python 套接字中使用 ntohl() 但接收函数 returns 字节,而 ntohl() 需要一个整数值作为输入。
这是我的代码
C端(仅相关部分):
uint32_t a[1] = {1231};
uint32_t a_converted[1]={0};
a_converted[0] = htonl(a[0]);
iResult = send( ConnectSocket, ( char *) a_converted, sizeof( a_converted), 0 );
Python 边(仅相关部分):
data = connection.recv(16)
data_i = socket.ntohl(data)
您说您已成功通过连接发送字符串。我假设您发送了一个 char*
并在 python 中收到了它作为一个字符串。你所做的是发送一个字节流。
现在您想发送一个整数数组。在内存中,整数再次存储为字节。 每个整数可能占用 4/8 字节。您可以通过打印
来事先检查printf("Size of integer is %zu", sizeof(int));
好的,很好,现在我们知道需要发送多少字节了。假设现在是 4。
我们还需要知道整数的字节序,但我们现在假设是大字节序。
这意味着最低有效字节在前,最高有效字节在最后。
所以现在您可以发送整数数组,方法是将数组转换为 char*
并发送 sizeof(array)
.
虽然在接收端,您只有一个字节流。要将其转换为整数数组,您需要一次获取 4 个字节并将其组合成一个整数。
我们可以这样做。
假设共有 10 个整数。您必须以某种方式单独传递此信息。
bytes = connection.recv(10*4)
array = []
for i in range(10):
x = ord(bytes[i*4+0])
x += ord(bytes[i*4+1]) << 8
x += ord(bytes[i*4+2]) << 16
x += ord(bytes[i*4+3]) << 24
array += [x]
print x
您将能够看到整数数组。
此处函数 ord
将一个字符转换为其 ASCII 等效整数。
旁注:
现在,如果您的系统的整数大小为 8 而不是 4,则您需要扩展 python 中的循环体。它将一直持续到 56。此外,每个索引(以字节为单位)将是 i*8+...
同样,如果字节顺序不同,元素的顺序也会改变。基本上 bytes
上的索引将从 i*4+3
变为 i*4+0
。
你收到的是一串字节,ntohl没有异常吗? 您可以使用 struct 模块解压 - 16 字节
struct.unpack('!4I', data)
含义 - 按网络顺序解压 4 个无符号 32 位整数
(我无法测试,请自行尝试)
编辑: 哎呀,没看完你的评论。根据 sockets docs,recv 应该 return 类型为 bytes 的对象。如果它 returns 类型为 str 的对象 - 您应该将其转换为 bytes - 在 Python3 中它将是 data.encode()
PS你在哪个Python?