繁体   English   中英

从TCP套接字读取错误的数据

[英]Reading wrong data from TCP socket

我正在尝试通过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协议可确保不会丢失任何数据,并且可以按正确的顺序接收所有内容,但是考虑到它已经在本地运行,那么这怎么可能呢?我在这里又犯了什么错误呢?

不能保证当您读取block_countblock_size ,您将一次性读取所有8个字节。

我给人的印象是TCP协议确保没有数据丢失,并且一切以正确的顺序接收

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

也许读取调用返回而没有读取完整的8个字节。 我会检查他们报告阅读了多长时间。

您可能还会发现valgrind或strace可以提供更多信息,以更好地理解代码为何以这种方式运行。 如果正在读取短数据,则strace会告诉您syscall返回的内容,而valgrind会告诉您正在读取长度变量中的未初始化字节。

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

但是,如果两个通信的机器具有不同的字节序来表示整数,例如x86与SPARC,或者sizeof(int)不同,例如64位与32位,则代码将无法正常工作。

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

当它无法正常工作时,我认为您会发现它们并不相同。 如果是这样,那么如果数据内容包含任何二进制数据,那么它的内容也会被误解。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM