这篇文章是在前一篇文章的基础上,添加并实现在点对点传输过程中,设计到位图操作的方法。
同时在 Main 方法中根据新加入的方法写入测试代码,对方法的正确性进行验证。
1. 添加的方法1
int Bitmap::restore_bitmap ( char *file_path )
功能描述
该方法可以将位图中的数值信息存储到 file_path 指定的路径下面,
文件的命名已经写入到程序中,无需设定。
路径名称后面不要加上 '/' 分隔符。
将位示图存储到文件中的主要作用是为了实现断点续传的功能。
2. 添加的方法2
int Bitmap::get_download_piece_num ()
功能描述
该方法用于统计位图中的bit 数值来统计当前客户端总共下载了
资源文件中的多少个 piece 的数值。在程序中bit = 1 代表的含义便是,
该 bit 对应的文件 piece 已经被下载到本地。
bit = 0 表示对应资源文件的 piece 还没有被下载到本地。
3. 添加的方法3
bool Bitmap::am_i_interested_in_peer ( Bitmap *peer )
功能描述
该方法是用来表示,传入的对等端 peer 上是否有当前客户端没有的文件块(pieces)
如果,对等端 peer 含有当前客户端没有的文件块,那么当前的客户端对该对等端 peer 是感兴趣的,
这种情形方法返回 true ,接下来便会进行点对点(peer)的文件互传(这个方法中并没有实现)。
如果,peer 与 当前客户端
1. 二者含有的资源文件不同,二者是不匹配的
2. peer 上含有的资源文件块与客户端上含有的资源文件块完全相同
3. peer 上含有的资源文件块要 < 客户端上的
4. peer 、当前客户端对象中的某些字段不合法
上述 4 中情形统统返回 false------------> 当前的客户端对对等端 peer 不感兴趣
代码如下:
// bit_map.h
-
#ifndef BIT_MAP_H
-
#define BIT_MAP_H
-
-
#include <vector>
-
-
class Bitmap
-
{
-
private:
-
std::vector<char> bit_field ;
-
int byte_length ;
-
int bit_length ;
-
public :
-
Bitmap () {}
-
Bitmap ( int need_bit_length )
-
{
-
bit_length = need_bit_length ;
-
byte_length = need_bit_length / 8 ;
-
-
// i am afriaid we need one more byte
-
if ( (need_bit_length%8) != 0 )
-
byte_length += 1 ;
-
-
for ( int i = 0 ; i < byte_length ; i++ )
-
{
-
unsigned char v = 0x00 ; //all bit initialized into 0
-
bit_field.push_back ( v ) ;
-
}
-
}
-
-
~Bitmap ()
-
{
-
bit_field.clear () ;
-
}
-
-
-
int get_bit_map_value ( int index ) ;
-
int set_bit_map_value ( int index , int set_value ) ;
-
int set_all ( int set_value ) ;
-
void print () ;
-
-
// add by Aimer 2015/4/17
-
int restore_bitmap ( char *file_path) ;
-
-
// add by Aimer 2015/4/17
-
int get_download_piece_num () ;
-
-
// add by Aimer 2015/4/17
-
bool am_i_interested_in_peer ( Bitmap *peer ) ;
-
-
} ;
-
-
#endif
// bit_map.cpp
-
#include <cstdio>
-
#include <cstdlib>
-
#include <iostream>
-
#include <vector>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
-
-
#include <glog/logging.h>
-
-
#include "bit_map.h"
-
-
#define set_value_one(value,index) value|=(1<<index)
-
#define set_value_zero(value,index) value&=~(1<<index)
-
-
-
using namespace std ;
-
-
int Bitmap::set_all ( int set_value )
-
{
-
char v ;
-
-
// first , we check set_value : this should be either 0 or 1
-
if ( set_value != 1 && set_value != 0 )
-
{
-
LOG(WARNING)<<"[warning] set value should be 0 or 1";
-
return -1 ;
-
}
-
-
// justify set_value = 1 or = 0
-
-
if ( set_value == 0 )
-
{
-
v = 0x00 ;
-
}
-
-
if ( set_value == 1 )
-
{
-
v = 0xff ;
-
}
-
for ( int i = 0 ; i < bit_field.size() ; i++ )
-
{
-
bit_field[i] = v ;
-
}
-
-
return 0 ;
-
}
-
-
-
int Bitmap::get_bit_map_value ( int index )
-
{
-
int pos_byte = index / 8 ;
-
int pos_bit = index % 8 ;
-
-
// first check whether index is leagal
-
// index increase by bit
-
-
if ( index < 0 || index > bit_length )
-
{
-
LOG(WARNING)<<"[warning] index not illegal ";
-
return -1 ;
-
}
-
-
if ( (bit_field[pos_byte] >> pos_bit)&1)
-
{
-
return 1 ;
-
}
-
-
else
-
{
-
return 0 ;
-
}
-
-
return -1 ; // this branch could not be reach
-
}
-
-
int Bitmap::set_bit_map_value ( int index, int set_value )
-
{
-
int pos_byte = index / 8 ;
-
int pos_bit = index % 8 ;
-
-
printf ("pos_byte %d pos_bit %d\n", pos_byte , pos_bit) ;
-
-
// index legal testing , incr by bits
-
-
if ( index < 0 || index >bit_length )
-
{
-
LOG(WARNING)<<"[warning] index illegal range";
-
return -1 ;
-
}
-
-
// then set_value
-
-
if ( set_value != 0 && set_value != 1 )
-
{
-
LOG(WARNING)<<"[warning] input set_value error ";
-
return -1 ;
-
}
-
-
char value = bit_field[pos_byte] ;
-
// now divide two branches by set_value = 1 or 0
-
if ( set_value == 1)
-
{
-
-
printf ("before %x \n", bit_field[pos_byte]) ;
-
// call set_value_one
-
set_value_one(value,pos_bit ) ;
-
bit_field[pos_byte] = value ;
-
printf ("after %x \n",bit_field[pos_byte]) ;
-
}
-
-
if ( set_value == 0 )
-
{
-
printf ("before %x \n", bit_field[pos_byte]) ;
-
// call set_value_zero
-
set_value_zero(value,pos_bit) ;
-
bit_field[pos_byte] = value ;
-
printf ("after %x \n", bit_field[pos_byte]) ;
-
}
-
-
-
return 0 ;
-
}
-
-
-
void Bitmap::print ()
-
{
-
// this method is used to output each bit in each unsigned char
-
// as element stored in each vector<char> bit_field ;
-
-
for ( int i = 0 ; i < bit_field.size() ;i++ )
-
{
-
for ( int j = 0 ; j < 7 ; j++ ) // each unsigned char has 8 bits [0...7]
-
{
-
if ( (bit_field[i] >> j) &1 )
-
printf ("1") ;
-
else
-
printf ("0") ;
-
}
-
-
// printf ("\n") ;
-
}
-
-
printf ("\n") ;
-
}
-
-
-
// add by Aimer 2015/4/17
-
int Bitmap::restore_bitmap ( char *file_path )
-
{
-
int fd ;
-
char file_name[64] ;
-
-
if (file_path==NULL)
-
{
-
LOG(WARNING)<<"[warning] file_path is empty" ;
-
return -1 ;
-
}
-
-
sprintf (file_name, "%s//bitmap%d.dat" , file_path , bit_length ) ;
-
fd = open ( file_name , O_RDWR | O_CREAT | O_TRUNC , 0666 ) ;
-
if ( fd < 0 )
-
{
-
LOG(WARNING)<<"[warning] failed to open file %s "<< file_name ;
-
return -1 ;
-
}
-
-
for ( int i = 0 ; i < bit_field.size () ;i++ )
-
{
-
if ((write ( fd , &bit_field[i], 1 ) ) != 1 )
-
{
-
LOG(WARNING)<<"[warning] failed in writing into file ,error in %d byte "<< i ;
-
return -1 ;
-
}
-
}
-
-
close ( fd ) ;
-
return 0 ;
-
}
-
-
// add by Aimer 2015/4/17
-
int Bitmap::get_download_piece_num ()
-
{
-
unsigned char test_char [8] =
-
{
-
0x80, // 1000 0000
-
0x40, // 0100 0000
-
0x20, // 0010 0000
-
0x10, // 0001 0000
-
0x08, // 0000 1000
-
0x04, // 0000 0100
-
0x02, // 0000 0010
-
0x01, // 0000 0001
-
} ;
-
-
int download_piece_num = 0 ;
-
for ( int i = 0 ; i < (byte_length-1); i++ )
-
{
-
for ( int j = 0 ; j < 8 ; j++ )
-
{
-
if ( test_char[j] & bit_field[i] )
-
download_piece_num++ ;
-
}
-
}
-
-
// the bit_length % 8 , mod remain bits count
-
int limit = (bit_length%8)?(bit_length%8):8 ;
-
-
for ( int j = 0 ; j < limit ; j++ )
-
if ( test_char[j] & bit_field[byte_length-1] )
-
download_piece_num ++ ;
-
-
return download_piece_num ;
-
}
-
-
// add by Aimer 2015/4/17
-
// this method is used to checkout whether "I" the current Bitmap object
-
// is interested in the resource pieces (represented by bit in bit_field)
-
// the peer the paramter (Bitmap*) holds
-
-
// if the peer holds the resources "I" don't have , return true
-
-
// else return false ,presents "I" have the same of more resource pieces
-
// the peer take , so "I" am not interested in peer
-
-
-
bool Bitmap::am_i_interested_in_peer ( Bitmap *peer )
-
{
-
unsigned char test_char[8] =
-
{0x80 , 0x40 , 0x20 , 0x10 , 0x08 , 0x04 , 0x02 , 0x01 } ;
-
unsigned char p_c , i_c ;
-
-
if ( peer == NULL )
-
{
-
LOG(WARNING)<<" peer is empty" ;
-
// printf ("reason %d \n" , __LINE__ ) ;
-
return false ;
-
}
-
-
if ( bit_field.size() == 0 || peer->bit_field.size() == 0 )
-
{
-
LOG(WARNING)<<"[warning] I and peer one or both of us has a empty bit map" ;
-
// printf ("reason %d \n" , __LINE__ ) ;
-
return false ;
-
}
-
-
if ((byte_length != peer->byte_length) ||
-
(bit_length != bit_length ))
-
{
-
LOG(WARNING)<<"[warning] I and peer valid bit length do not match" ;
-
// printf ("reason %d \n" , __LINE__ ) ;
-
return false ;
-
}
-
-
-
-
for ( int i = 0 ; i < ( byte_length -1 ); i++ )
-
{
-
for ( int j = 0 ; j < 8 ; j++ )
-
{
-
i_c = ( bit_field[i] & test_char[j] ) ;
-
p_c = ( peer->bit_field[i] & test_char[j]);
-
-
if ( i_c == 0 && p_c > 0 )
-
{
-
// "I" do not have the resource piece peer has
-
// "I" am intrested in peer
-
-
return true ;
-
}
-
}
-
}
-
-
-
int limit = (bit_length%8)?(bit_length%8):8 ;
-
-
for ( int j = 0 ; j < limit ; j++ )
-
{
-
i_c = (bit_field[byte_length-1] & test_char[j] ) ;
-
p_c = (bit_field[byte_length-1] & test_char[j]) ;
-
-
if ( i_c > 0 && p_c == 0 )
-
return true ;
-
}
-
-
return false ;
-
}
// Main.cpp
-
#include <cstdio>
-
#include <cstdlib>
-
#include <iostream>
-
#include <vector>
-
#include <glog/logging.h>
-
#include "bit_map.h"
-
-
using namespace std ;
-
-
int main ( int argc , char **argv )
-
{
-
int need_bit_length = 1024 ;
-
-
// initialize log system
-
google::InitGoogleLogging( argv[0] ) ;
-
// set log path
-
FLAGS_log_dir = "./log/" ;
-
-
// test Bitmap's constructor
-
Bitmap bitMap(need_bit_length) ;
-
-
// test Bitmap's set all
-
bitMap.set_all( 1 ) ;
-
-
// test Bitmap's print
-
bitMap.print () ;
-
-
int index = 5 ;
-
-
// test Bitmap's set_bit_map_value
-
bitMap.set_bit_map_value ( index , 0 ) ;
-
-
bitMap.print () ;
-
-
// test Bitmap's get_bit_map_value
-
-
int result = bitMap.get_bit_map_value ( index ) ;
-
// it must should be 0
-
-
printf (" get value = %d \n",result ) ;
-
-
// test Bitmap's restore_bitmap
-
char file_path [64] ;
-
-
printf ("input file path to store bitmap content into file \n") ;
-
scanf ("%s" , file_path) ;
-
bitMap.restore_bitmap ( file_path ) ;
-
-
-
// test Bitmap's get_download_piece_num
-
int download_counter =
-
bitMap.get_download_piece_num () ;
-
// 1023 should be the right result
-
printf ("download_piece_num : %d \n" , download_counter ) ;
-
-
-
// test Bitmap's am_i_interested_in_peer
-
Bitmap peer_bitMap ( 1024 ) ;
-
peer_bitMap.set_all (1) ;
-
-
if ( bitMap.am_i_interested_in_peer ( &peer_bitMap ) )
-
{
-
printf ("I am interested in peer's resource pieces \n") ;
-
}
-
else
-
{
-
printf ("I am not interested in peer's reousrce pieces \n") ;
-
}
-
-
return 0 ;
-
}
end
阅读(1371) | 评论(1) | 转发(0) |