通过TCP发送int数组时,为什么只有第一个数量正确?

时间:2009-03-23 17:59:46

标签: c sockets tcp

按照我之前的问题(Why do I get weird results when reading an array of integers from a TCP socket?),我提出了以下代码,它似乎有用。代码示例适用于少量数组元素,但一旦变大,数据就会在最后被破坏。

这是通过TCP发送int数组的代码:

#define ARRAY_LEN 262144

long *sourceArrayPointer = getSourceArray();

long sourceArray[ARRAY_LEN];
for (int i = 0; i < ARRAY_LEN; i++)
{
    sourceArray[i] = sourceArrayPointer[i];
}

int result = send(clientSocketFD, sourceArray, sizeof(long) * ARRAY_LEN);

这是接收int数组的代码:

#define ARRAY_LEN 262144

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

前几个数字很好,但是在阵列的下方,数字开始变得完全不同了。最后,当数字看起来像这样:

0
0
0
0
0
0
0
0
0
0

但他们实际上是这样出来的?

4310701
0
-12288
32767
-1
-1
10
0
-12288
32767

这是因为我使用了错误的发送/接收尺寸吗?

6 个答案:

答案 0 :(得分:7)

read(..., len)的调用不会从套接字读取len个字节,它最多会读取len个字节。您的阵列相当大,它将被拆分为许多TCP / IP数据包,因此您的read调用可能只返回数组的一部分,而其余部分仍在“传输中”。 read()返回它收到的字节数,所以你应该再次调用它,直到你收到你想要的一切。你可以这样做:

long targetArray[ARRAY_LEN];

char *buffer = (char*)targetArray;
size_t remaining = sizeof(long) * ARRAY_LEN;
while (remaining) {
  ssize_t recvd = read(socketFD, buffer, remaining);
  // TODO: check for read errors etc here...
  remaining -= recvd;
  buffer += recvd;
}

答案 1 :(得分:5)

以下是否可以?

for (int i = 0; sourceArrayPointer < i; i++)

您正在比较苹果和橙子(读指针和整数)。由于long s数组的指针是&gt;,因此该循环不会被执行。 0(最常见)。因此,在接收端,您正在读取一个单位化数组,导致传递的数字不正确)。

更确切地说是:

for (int i = 0; i < ARRAY_LEN; i++)

答案 2 :(得分:1)

答案 3 :(得分:0)

与此问题无关,但如果您想在不同平台上使用TCP,则还需要处理endianness平台。

使用像curl或ACE这样的网络库要简单得多,如果这是一个选项(另外你在更高层次上学习更多设计模式)。

答案 4 :(得分:0)

没有什么可以保证TCP如何将您发送到数据流的数据分组 - 它只能保证它在应用程序级别以正确的顺序结束。因此,您需要检查结果的值,并继续读取,直到您已读取正确的字节数。否则你将无法读取整个数据。你使用长数组而不是字节数组使自己变得更加困难 - 数据可以以任意数量的块发送,这些块可能不会与长边界对齐。

答案 5 :(得分:0)

我在这里看到了许多问题。首先,我会按照我的理解重写您的发送代码。我假设getSourceArray总是返回一个指向大小为ARRAY_LEN的静态或malloced缓冲区的有效指针。我还假设您稍后在代码中不需要sourceArrayPointer。

#define ARRAY_LEN 262144

long *sourceArrayPointer = getSourceArray();

long sourceArray[ARRAY_LEN];
long *sourceArrayIdx = sourceArray;

for (; sourceArrayIdx < sourceArray+ARRAY_LEN ; )
    sourceArrayIdx++ = sourceArrayPointer++;

int result = send(clientSocketFD, sourceArray, sizeof(long) * ARRAY_LEN);
if (result < sizeof(long) * ARRAY_LEN)
    printf("send returned %d\n", result);

查看你的原始代码我猜你的for循环搞砸了并且从不执​​行导致你发送任何随机垃圾恰好在内存sourceArray指向的地方。基本上你的条件

sourceArrayPointer < i;

几乎可以保证第一次失败。