【问题标题】:Python socket: cannot receive int arrayPython套接字:无法接收int数组
【发布时间】:2018-05-06 05:57:03
【问题描述】:

我尝试通过 winsockets 在 Python 和 c 程序之间进行进程间通信。发送字符串确实有效,但现在我尝试将一个 int 数组从 c 套接字发送到 python 套接字。

我已经发现,winsock2的send函数不能直接发送int数组,所以必须使用htonl()将int数组转换为字节流。

现在我想在 python 套接字中使用 ntohl(),但接收函数返回字节,而 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)

【问题讨论】:

  • 您确实不必在发送之前必须htonl int。根本没有理由,除非您定义了需要它的协议。如果您确定服务器和客户端都使用相同的字节序,请按原样发送。
  • 但我仍然必须将 int 数组转换为 const char *buf,它确实可以正常工作

标签: python c sockets typeerror htonl


【解决方案1】:

你收到的是一串字节,ntohl没有引起异常吗? 您可以使用 struct 模块来解压 - 16 个字节

struct.unpack('!4I', data)

含义 - 按网络顺序解压缩 4 个无符号 32 位整数

RTM

(我无法测试 - 请自行尝试)

编辑: 糟糕,没有阅读您的评论。根据sockets docsrecv 应该返回 bytes 类型的对象。如果它返回 str 类型的对象 - 你应该将它转换为 bytes - 在 Python3 中它将是 data.encode()

PS 你在哪个 Python 上?

【讨论】:

  • 我不得不将其更改为 test =struct.unpack('
  • 但它总是抛出错误: struct.error: unpack requires a bytes object of length 16. 我检查了数据的长度,它是 16。 解压数据的打印与它看起来在 c 套接字中
  • 我发现了我的错误: unpack 方法是正确的,因为 recv 返回一个字节数组。 recv 发生在一个循环中,并且在第二次运行时接收缓冲区为空,这会导致故障。一个简单的检查数据是否为空解决了这个问题:)
【解决方案2】:

您说您已设法通过连接发送字符串。我假设您发送了 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() 实际上具有误导性。使用您的代码,我得到错误 TypeError: ord() expected string of length 1, but int found
  • Python 有用于处理通信数据的工具 - struct 在最低级别。你正在重新发明一个轮子——你的轮班方向是错误的! range 函数有一个 step 参数
猜你喜欢
  • 2016-02-28
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
  • 2020-09-24
  • 1970-01-01
相关资源
最近更新 更多