2012-11-06 77 views
1

我试图通过TCP套接字发送数据块。服务器代码执行以下操作:从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(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块(A〜587字节)左右做工精细,但后来我得到一个不正确的block_size阅读:

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

然后它崩溃了,很明显。 我的印象是TCP协议确保没有数据丢失,并且所有信息都按正确的顺序接收,但是考虑到它已经在本地工作,那么这怎么可能?我的错误在哪里?

+0

您是否检查过服务器中的列表实际上是否有效?即'p-> next'对于最后一个节点是'NULL'。 –

回答

4

无法保证当您阅读block_countblock_size时,您将一次读取全部8个字节。

1

我的印象是,TCP协议保证没有数据丢失 ,一切都在正确的顺序

是接收,但是这是所有TCP保证。它不保证数据在单个数据包中发送和接收。您需要收集数据并将它们放在缓冲区中,直到在复制数据之前获得所需的块大小。

1

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

您可能还会发现valgrind或strace提供信息,以便更好地理解您的代码为何如此行事。如果你读取的是短读,strace会告诉你系统调用返回的是什么,valgrind会告诉你,你正在读取长度变量中未初始化的字节。

1

它在同一台机器上工作的原因是block_size和block_count是作为二进制值发送的,当它们被客户端接收和解释时,它们具有相同的值。然而,如果两个通信机器具有不同的用于表示整数的字节顺序,例如,如果两个机器通信的字节顺序不同, x86与SPARC或sizeof(int)是不同的,例如, 64位与32位,那么代码将无法正常工作。

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

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