【问题标题】:Why do I get weird results when reading an array of integers from a TCP socket?为什么从 TCP 套接字读取整数数组时会得到奇怪的结果?
【发布时间】:2010-10-14 23:59:43
【问题描述】:

正如我在上一个问题 (How do I send an array of integers over TCP in C?) 的回答中所建议的那样,我尝试发送一个 long int 数组,但是我可能正在做一些事情来破坏解决方案...

#define ARRAY_LEN 4

/* I'm using long because the numbers are very large,
 * but in this example they're small to save space. */
long originalArray[ARRAY_LEN] = { 1, 2, 3, 4 };

myObject.SetMyArray(originalArray);

// NOTE: The following is in a different function.

long *myArrayFromFunction = myObject.GetMyArray();

write(clientSocketFD, myArrayFromFunction, sizeof(myArrayFromFunction) * ARRAY_LEN);

转换成指针然后传递不正确吗?

在客户端读取时,我得到的不是我发送的数字(1、2、3、4),而是长数字,例如 140088443806649...

#define ARRAY_LEN 4

long targetArray[ARRAY_LEN];
read(socketFD, targetArray, sizeof(targetArray) * ARRAY_LEN);

所以,假设我需要读入一个指针,我尝试了这个......

#define ARRAY_LEN 4

long *targetArray;
read(socketFD, targetArray, sizeof(targetArray) * ARRAY_LEN);

但这也不起作用(读取函数返回 -1)。

【问题讨论】:

  • 两端机器字节序是否相同?
  • 在引用的答案中,示例代码在整数数组前面加上数组的大小。这必须在接收端解码。
  • 您会添加用于每个端点的平台架构吗?
  • 目前只是在本地工作......所以它是同一台机器。
  • @Nick:你的最后一个例子由于多种原因被严重破坏。 #1 你没有为 targetArray 分配任何内存来指向。 #2,sizeof 也坏了。这将返回“long *”而不是“long”的大小(可能相等也可能不相等)。

标签: c sockets tcp


【解决方案1】:

额外的指针是不必要的。数组(基本上是一个指针)可以直接传递。您错误地使用了指针的大小而不是数据类型的大小(长);请改用sizeof (long) * ARRAY_LEN 或只使用sizeof (originalArray)

写:

#define ARRAY_LEN 4
long originalArray[ARRAY_LEN] = { 1, 2, 3, 4 };
write(clientSocketFD, originalArray, sizeof (originalArray));

阅读:

#define ARRAY_LEN 4
long targetArray[ARRAY_LEN];
read(socketFD, targetArray, sizeof (targetArray));

如果您将数组作为指针传递,则sizeof 不能用于获取数组的总大小。在这种情况下,大小必须与指针以及由sizeof (long) * ARRAY_LEN 构造的大小一起传递。

小心使用 long 等类型,因为它在不同平台上的大小并不总是相同(即 32 位与 64 位);改用 int32_t 之类的大小类型。此外,您也可能遇到endianess 的问题。考虑在写入之前用htonl 对值进行字节交换。

【讨论】:

  • 是的,但是如果数组来自函数怎么办,因为你知道你不能从函数返回数组,所以我不得不使用指针。你是说指针应该转换回原来的数组形式?
  • @Nick:那么你应该使用 sizeof(long) * element_count 作为发送的大小。
【解决方案2】:

我还想指出,在某些情况下,存储在内存中的数据和通过网络发送的数据的不同字节序可能是问题的原因,因此如果您在低级别工作,请务必检查这一点。

【讨论】:

  • 这在过去肯定是个问题,但现在大多数软件都运行在英特尔架构上。当然,如果您将数据发送到 Unix 服务器并且您不知道它是 Intel、SPARC、Power 还是其他不同的服务器,则需要考虑这一点。
  • 在 x86 上在 C 和 Java 之间传递数据也需要反转字节序。
  • “过去是个问题,但现在大多数软件都运行在英特尔架构上。”你是认真的吗?错误的态度来编写高质量的代码恕我直言。
【解决方案3】:

如果您正在编写自己的 TCPStream 或其他代码,您可能想查看 http://smartwinlib.org 中的 SmartNetwork 代码...

它包含从 TCP 一直到 HTTP 甚至 SOAP 的所有流包装器,并且代码非常很小,但模板化程度很高...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    • 2016-01-23
    • 2018-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多