简体   繁体   English

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

[英]Reading wrong data from TCP socket

I'm trying to send data blockwise over a TCP socket. 我正在尝试通过TCP套接字逐块发送数据。 The server code does the following: 服务器代码执行以下操作:

#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));
}

On the client side, I read the size and then the data (same CHECK makro): 在客户端,我先读取大小,然后读取数据(相同的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;
  }
}

This works perfectly fine as long as both client and server run on the same machine, but as soon as I try this over the network, it fails at some point. 只要客户端和服务器都在同一台计算机上运行,​​此方法就可以很好地工作,但是一旦我通过网络尝试此操作,它有时就会失败。 In particular, the first 300-400 blocks (à ~587 bytes) or so work fine, but then I get an incorrect block_size reading: 特别是前300-400个块(约587字节)可以正常工作,但随后我得到了不正确的block_size读数:

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

And then it crashes, obviously. 然后很显然它崩溃了。 I was under the impression that the TCP protocol ensures no data is lost and everything is received in correct order, but then how is this possible and what's my mistake here, considering that it already works locally? 我给人的印象是,TCP协议可确保不会丢失任何数据,并且可以按正确的顺序接收所有内容,但是考虑到它已经在本地运行,那么这怎么可能呢?我在这里又犯了什么错误呢?

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

I was under the impression that the TCP protocol ensures no data is lost and everything is received in correct order 我给人的印象是TCP协议确保没有数据丢失,并且一切以正确的顺序接收

Yes, but that's all that TCP guarantees. 是的,但这就是TCP保证的全部。 It does not guarantee that the data is sent and received in a single packet. 它不能保证在单个数据包中发送和接收数据。 You need to gather the data and piece them together in a buffer until you get the block size you want before copying the data out. 您需要收集数据并将它们组合在缓冲区中,直到获得所需的块大小为止,然后再将数据复制出来。

Perhaps the read calls are returning without reading the full 8 bytes. 也许读取调用返回而没有读取完整的8个字节。 I'd check what length they report they've read. 我会检查他们报告阅读了多长时间。

You might also find valgrind or strace informative for better understanding why your code is behaving this way. 您可能还会发现valgrind或strace可以提供更多信息,以更好地理解代码为何以这种方式运行。 If you're getting short reads, strace will tell you what the syscalls returned, and valgrind will tell you that you're reading uninitialized bytes in your length variables. 如果正在读取短数据,则strace会告诉您syscall返回的内容,而valgrind会告诉您正在读取长度变量中的未初始化字节。

The reason why it works on the same machine is that the block_size and block_count are sent as binary values and when they are received and interpreted by the client, they have same values. 它在同一台机器上工作的原因是,block_size和block_count是作为二进制值发送的,并且当客户端接收并解释它们时,它们具有相同的值。

However, if two machines communicating have different byte order for representing integers, eg x86 versus SPARC, or sizeof(int) is different, eg 64 bit versus 32 bit, then the code will not work correctly. 但是,如果两个通信的机器具有不同的字节序来表示整数,例如x86与SPARC,或者sizeof(int)不同,例如64位与32位,则代码将无法正常工作。

You need to verify that sizeof(int) and byte order of both machines is identical. 您需要验证两台计算机的sizeof(int)和字节顺序是否相同。 On the server side, print out sizeof(int) and values of storage->length and p->blocksize. 在服务器端,打印出sizeof(int)以及storage-> length和p-> blocksize的值。 On the client side print out sizeof(int) and values of block_count and block_size. 在客户端打印出sizeof(int)以及block_count和block_size的值。

When it doesn't work correctly, I think you will find them that they are not the same. 当它无法正常工作时,我认为您会发现它们并不相同。 If this is true, then the contents of data is also going to be misinterpreted if it contains any binary data. 如果是这样,那么如果数据内容包含任何二进制数据,那么它的内容也会被误解。

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

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