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

按照我之前的问题( 为什么我从TCP套接字读取整数数组时会得到奇怪的结果? ),我提出了以下代码,这似乎有用。 代码示例适用于少量数组元素,但一旦变大,数据就会在最后被破坏。

这是通过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 

这是因为我使用了错误的发送/接收大小?

read(..., len)的调用不会从套接字读取len个字节,它会读取最大len个字节。 您的arrays相当大,它将被拆分为许多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; } 

以下是否可以?

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

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

它宁愿是:

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

与此问题无关,但如果要在不同平台上使用TCP,还需要注意平台的字节顺序 。

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

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

我在这看到一些问题。 首先,这就是我如何理解它重写你的发送代码。 我假设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; 

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