openssl 内部封装的哈希

1、在一般的数据结构如线性表和树中,记录在结构中的相对位置是与记录的关键字之间不存在确定的关系,在结构中查找记录时需进行一系列的关键字比较。这一类查找方法建立在“比较”的基础上,查找的效率与比较次数密切相关。理想的情况是能直接找到需要的记录,因此必须在记录的存储位置和它的关键字之间建立确定的对应关系,使每个关键字和结构中一个唯一的存储位置相对应。在查找时,只需根据这个对应关系找到给定值。这种对应关系既是哈希函数,按这个思想建立的表为哈希表。哈希表存在冲突现象:不同的关键字可能得到同一哈希地址。在建造哈希表时不仅要设定一个好的哈希函数,而且要设定一种处理冲突的方法。

2、数据结构

​ OpenSSL函数使用哈希表来加快查询操作,并能存放任意形式的数据,比如配置文件的读取、内存分配中被分配内存的信息等。

typedef struct lhash_node_st {
    void *data;
    struct lhash_node_st *next;
    #ifndef OPENSSL_NO_HASH_COMP
    unsigned long hash;
    #endif
} LHASH_NODE;
//data用于存放数据地址,next为下一个数据地址,hash为数据哈希计算值。
typedef struct lhash_st {
   	 LHASH_NODE **b;  
     LHASH_COMP_FN_TYPE comp;  
     LHASH_HASH_FN_TYPE hash;  
     unsigned int num_nodes;  
     unsigned int num_alloc_nodes;  
     unsigned int p;  
     unsigned int pmax;  
     unsigned long up_load; /* load times 256 */   unsigned long down_load; /* load times 256 */  unsigned long num_items;  
     unsigned long num_expands;  
     unsigned long num_expand_reallocs;  
     unsigned long num_contracts;  
     unsigned long num_contract_reallocs;   unsigned long num_hash_calls;  
     unsigned long num_comp_calls;  
     unsigned long num_insert;  
     unsigned long num_replace;  
     unsigned long num_delete;  
     unsigned long num_no_delete;  
     unsigned long num_retrieve;  
     unsigned long num_retrieve_miss;  
     unsigned long num_hash_comps;  
     int error;  
 } LHASH;  
//其中,b指针数组用于存放所有的数据,数组中的每一个值为数据链表的头指针;comp用于存放数据比较函数地址;hash用于存放计算哈希值函数的地址;num_nodes为链表个数;num_alloc_nodes为b分配空间的大小。  

哈希结构

3、openssl内哈希函数

  1. LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c)
    功能:生成哈希表
    说明:输入参数h为哈希函数,c为比较函数。这两个函数都是回调函数。 因为哈希表用于存放任意的数据结构,哈希表存放、查询、删除等操作都需要比较数据和进行哈希运算,而哈希表不知道用户数据如何进行比较,也不知道用户数据结构中需要对哪些关键项进行散列运算。所以,用户必须提供这两个回调函数。

  2. void *lh_delete(LHASH *lh, const void *data)
    功能:删除散列表中的一个数据
    说明:data为数据结构指针。

  3. void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func)
    功能:处理哈希表中的所有数据
    说明:func为外部提供的回调函数,本函数遍历所有存储在哈希表中的数据,每个数据被func处理。

  4. void lh_doall_arg(LHASH lh, LHASH_DOALL_ARG_FN_TYPE func, voidarg)
    功能:处理哈希表中所有数据
    说明:此参数类似于lh_doall 函数,func为外部提供的回调函数,arg为传递给func函数的参数。本函数遍历所有存储在哈希表中的数据,每个数据被func处理。

  1. void lh_free(LHASH *lh)
    功能:释放哈希表。
  1. void *lh_insert(LHASH *lh, void *data)
    功能:往哈希表中添加数据。
    说明:data为需要添加数据结构的指针地址。

  2. void *lh_retrieve(LHASH *lh, const void *data)
    功能:查询数据。
    说明:从哈希表中查询数据,data为数据结构地址,此数据结构中必须提供关键项(这些关键项对应于用户提供的哈希函数和比较函数)以供查询,如果查询成功,返回数据结构的地址,否则返回NULL。比如SSL握手中服务端查询以前存储的SESSION时,它需要提供其中关键的几项:

    SSL_SESSION *ret=NULL,datadata.ssl_version=s->version;
    data.session_id_length=len;
    memcpy(data.session_id,session_id,len);
    ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data);

  3. void lh_node_stats_bio(const LHASH *lh, BIO *out)
    功能:将哈希表中每个链表下的数据状态输出到BIO中。

  4. void lh_node_stats(const LHASH *lh, FILE *fp)
    功能:将哈希表中每个链表下数据到个数输出到FILE中。
    说明:此函数调用了lh_node_stats_bio函数。

  5. void lh_node_usage_stats_bio(const LHASH *lh, BIO *out)源文件:lh_stats.c
    功能:将哈希表的使用状态输出到BIO中。

  6. void lh_node_usage_stats(const LHASH *lh, FILE *fp)源文件:lh_stats.c
    功能:将哈希表的使用状态输出到FILE中
    说明:此函数调用了lh_node_usage_stats_bio函数

  7. unsigned long lh_num_items(const LHASH *lh)
    功能:获取哈希表中元素的个数。

  8. void lh_stats_bio(const LHASH *lh, BIO *out)
    功能:输出哈希表统计信息到BIO中

  9. void lh_stats(const LHASH *lh, FILE *fp)
    功能:打印哈希表的统计信息,此函数调用了lh_stats_bio。

  10. unsigned long lh_strhash(const char *c)

    功能:计算文本字符串到哈希值。

4、demo

#include <stdio.h>
#include <string>
#include <openssl/lhash.h>

#define NAME_LENGTH		32

typedef struct _Student {

	char name[NAME_LENGTH];
	int high;
	char student_info[NAME_LENGTH];

} Student;


static int person_cmp(const void *a, const void *b) {

	char *namea = ((Student*)a)->name;
	char *nameb = ((Student*)b)->name;

	return strcmp(namea, nameb);
}

void print_value(void *a) {
	Student *p = (Student*)a;

	printf("name: %s\n", p->name);
	printf("high: %d\n", p->high);
	printf("other info : %s\n", p->student_info);
}

int main() {

	//生成哈希函数
	_LHASH *h = lh_new(NULL, person_cmp);
	if (h == NULL) {
		printf("err.\n");
		return -1;
	}

	
	Student p1 = { "LiMing", 170, "xxxx" };
	Student p2 = { "XiaoHong", 175, "xxxx" };
	Student p3 = { "XiaoMing", 170, "xxxx" };

	//往哈希表中添加数据
	lh_insert(h, &p1);
	lh_insert(h, &p2);
	lh_insert(h, &p3);

	//处理哈希表中所有数据
	lh_doall(h, print_value);

	printf("\n\n\n------------------------------\n\n\n");

	//根据键值查询哈希值
	void *data = lh_retrieve(h, (const char *)"LiMing");
	if (data == NULL) {
		return -1;
	}

	print_value(data);

	//释放哈希表
	lh_free(h);

	return 0;
}

运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值