【问题标题】:Reading wrong data from TCP socket从 TCP 套接字读取错误数据
【发布时间】:2012-11-06 08:38:06
【问题描述】:

我正在尝试通过 TCP 套接字逐块发送数据。服务器代码执行以下操作:

#define CHECK(n) if((r=n) <= 0) { perror("Socket error\n"); exit(-1); }
int r;

//send the number of blocks
CHECK(write(sockfd, &(storage->length), 8)); //p->length is uint64_t

for(p=storage->first; p!=NULL; p=p->next) {
  //send the size of this block
  CHECK(write(sockfd, &(p->blocksize), 8)); //p->blocksize is uint64_t

  //send data
  CHECK(write(sockfd, &(p->data), p->blocksize));
}

在客户端,我读取大小,然后读取数据(相同的 CHECK makro):

CHECK(read(sockfd, &block_count, 8));
for(i=0; i<block_count; i++) {
  uint64_t block_size;
  CHECK(read(sockfd, &block_size, 8));

  uint64_t read_in=0;
  while(read_in < block_size) {
    r = read(sockfd, data+read_in, block_size-read_in); //assume data was previously allocated as char*
    read_in += r;
  }
}

只要客户端和服务器都在同一台机器上运行,它就可以很好地工作,但是一旦我通过网络尝试它,它就会在某些时候失败。特别是,前 300-400 个块(à ~587 字节)左右工作正常,但随后我得到一个不正确的 block_size 读数:

received block #372 size : 586
read_in: 586 of 586
received block #373 size : 2526107515908

然后它显然崩溃了。 我的印象是 TCP 协议确保不会丢失任何数据并且以正确的顺序接收所有内容,但是考虑到它已经在本地工作,这怎么可能?我的错误是什么?

【问题讨论】:

  • 你检查过服务器中的列表确实有效吗? IE。 p-&gt;next 是最后一个节点的 NULL

标签: c linux sockets networking tcp


【解决方案1】:

无法保证当您阅读 block_countblock_size 时,您会一口气读完所有 8 个字节。

【讨论】:

    【解决方案2】:

    我的印象是 TCP 协议确保没有数据是 丢失了,一切都按正确的顺序收到了

    是的,但这就是 TCP 的全部保证。它不保证在单个数据包中发送和接收数据。您需要收集数据并将它们拼凑在缓冲区中,直到获得所需的块大小,然后再将数据复制出来。

    【讨论】:

      【解决方案3】:

      也许读取调用在没有读取完整的 8 个字节的情况下返回。我会检查他们报告的阅读长度。

      您可能还会发现 valgrind 或 strace 信息丰富,可以更好地理解您的代码为什么会这样。如果你的读取时间很短,strace 会告诉你系统调用返回了什么,valgrind 会告诉你正在读取长度变量中未初始化的字节。

      【讨论】:

        【解决方案4】:

        它在同一台机器上工作的原因是block_size和block_count作为二进制值发送,当它们被客户端接收和解释时,它们具有相同的值。

        但是,如果两台机器通信时使用不同的字节顺序来表示整数,例如x86 与 SPARC 或 sizeof(int) 不同,例如64 位与 32 位,那么代码将无法正常工作。

        您需要验证两台机器的 sizeof(int) 和字节顺序是否相同。在服务器端,打印出 sizeof(int) 以及 storage->length 和 p->blocksize 的值。在客户端打印出 sizeof(int) 以及 block_count 和 block_size 的值。

        当它不能正常工作时,我想你会发现它们不一样。如果这是真的,那么如果数据的内容包含任何二进制数据,它也会被误解。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-04-02
          • 1970-01-01
          • 1970-01-01
          • 2011-02-26
          • 2014-09-15
          • 1970-01-01
          • 2020-07-07
          • 2016-08-10
          相关资源
          最近更新 更多