libevent 初探:手动编译运行安装包下的 sample 示例程序

一、引言

最近在工作中接触到了 libevent 库,老大想让我用 libevent 做一些网关相关的开发工作。因此,在这个不一样的春节里(肆虐的新冠病毒)我一直在阅读有关 libevent 相关的资料。

学习 libevent 的资料,我选择了最稳妥也是最慢的方法,libevent 的官方教程文档。这个文档大概在 2012 年之后就没有再更新了,国内也有朋友制作成了 pdf 方便大家阅读,我大概看了下,有 126 页之多。这里值得一说的就是,libevent 的官方教程文档还是写的很不错的,内容循序渐进,即使是英文,高中水平应该也是可以很顺畅的阅读的。

libevent 的详细介绍在 libevent 官网(http://libevent.org/) 上都有详细的介绍,实际上也有很多中国的程序员写的博客可以阅读。不过最详细最权威的,还是 libevent 的官方文档。

在 libevent 官网上,你可以看到 libevent 目前维护了 4 个版本:

1.4.x.stable
2.0.x.stable
2.1.x.stable
master

其中最新的稳定版本是 2.1.x.stable,master 是开发分支的最新代码,不具有生产使用意义。不过这里使用哪个版本不仅需要跟你的系统有关,还需要考虑其配套使用的 openssl 库的版本限制。

不过废话少说,这篇博客的目标读者是刚接触 libevent 的新手,对于新手来说,刚读完了(或者正在读)libevent 官方文档,最想做的事情是什么呢:

当然是把 libevent 安装包里面的 sample 程序跑起来了:)

这里,我基于 libevent 2.1.x.stable 版本的最新安装包 libevent-2.1.11-stable.tar.gz 进行讲解。

二、sample 示例程序编译

sample 下的程序实际上在 make 的时候就会自动生成,在 sample 下有以下程序:

sample/dns-example
sample/event-read-fifo
sample/hello-world
sample/http-server
sample/http-connect
sample/signal-test
sample/time-test
sample/le-proxy
sample/https-client

这些程序在你 make 完了之后就会自动生成。

编译方式在哪里看呢

我们可以打开 sample 文件夹下的 include.am 文件,这里记录了 sample 下面的程序的编译方式:

SAMPLES = \
	sample/dns-example				\
	sample/event-read-fifo			\
	sample/hello-world				\
	sample/http-server				\
	sample/http-connect				\
	sample/signal-test				\
	sample/time-test

if OPENSSL
SAMPLES += sample/le-proxy
sample_le_proxy_SOURCES = sample/le-proxy.c
sample_le_proxy_LDADD = libevent.la libevent_openssl.la $(OPENSSL_LIBS) $(OPENSSL_LIBADD)
sample_le_proxy_CPPFLAGS = $(AM_CPPFLAGS) $(OPENSSL_INCS)

SAMPLES += sample/https-client
sample_https_client_SOURCES = \
	sample/https-client.c \
	sample/hostcheck.c \
	sample/openssl_hostname_validation.c
sample_https_client_LDADD = libevent.la libevent_openssl.la $(OPENSSL_LIBS) $(OPENSSL_LIBADD)
sample_https_client_CPPFLAGS = $(AM_CPPFLAGS) $(OPENSSL_INCS)
noinst_HEADERS += \
	sample/hostcheck.h \
	sample/openssl_hostname_validation.h
endif

代码我们不需要完全看懂,我们大概就能看得出来有 3 种编译的方式。

只需要链接 libevent 库

只需要链接 libevent 库的编译方式:

$ gcc -o hello-world hello-world.c -levent

如果你是按照默认的方式安装的 libevent,也就是:

$ ./configure
$ make
$ sudo make install

那么,你的 libevent 多半就安装在 /usr/local 下,其中 /usr/local/lib 下放置了 libevent 的相关库文件,而 /usr/local/include 下则放置了 libevent的相关头文件。

这里,可能会有些朋友在执行 hello-world 的时候出现错误:

$ ./hello-world

执行后报错:

error while loading shared libraries: libevent-2.1.so.7: cannot open shared object file: No such file or directory

这是为什么呢?这是因为在运行的时候,ldd 程序找不到你所说的 libevent 库文件。那么怎么才能让它找得到呢,这里我通过查找资料,找到了一个解决办法:

1. 查看 hello-world 程序有哪一个库没有找到:

$ ldd ./hello-world

输出:

linux-vdso.so.1 (0x00007fffd55f7000)
libevent-2.1.so.7 => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4be8160000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4be7f40000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4be8a00000)

2. 将没找到的 libevent-2.1.so.7 库软连接到 ldd 默认扫描的目录 /usr/lib 下:

$ sudo ln -s /usr/local/lib/libevent-2.1.so.7 /usr/lib/libevent-2.1.so.7

因为是操作 /usr/lib 文件夹内容,因此需要 sudo 提高权限。

3. 重新运行 hello-world 即可

$ ./hello-world

这里的解决思路很简单,你的 ldd 不是找不到 libevent 库文件吗,那么我自己软连接一个 ldd 默认搜索的地方,然后连接到我库的地方即可。

ps:

a. 这个方法参考博客 error while loading shared libraries: libevent-2.0.so.5解决办法
b. 实际上还有其他方法,可以参考博客 “error while loading shared libraries: xxx.so.x” 错误的原因和解决办法

除了 libevent 库,还需要再链接一个 libevent_openssl 库

通过 sample 文件夹下的 include.am 文件,我们得知 le-proxy.c 文件的编译还需要添加一个 libevent_openssl 库。编译的语句也很简单:

$ gcc -o le-proxy le-proxy.c -levent -levent_openssl -lcrypto -lssl -I ../

注意:这里链接 libevent_openssl 库,还需要链接 openssl 的库文件,也就是 libcrypto 和 libssl,这两个库不能少。另外,le-proxy.c 还有一个头文件位于 sample 上一层文件夹,也需要指定头文件包含。

有些朋友在编译 le-proxy.c 的时候可能会发现:

在自己的 /usr/local/include/event2 下(假定你也是按照默认安装路径 /usr/local 进行安装)根本就没有 bufferevent_ssl.h 头文件存在!再仔细一看,发现根本就没有生成 libevent_openssl 库文件!

这当然会导致 le-proxy.c 编译失败。

那么这是为什么呢:

因为在 libevent 的安装过程中,如果它能够找到 openssl 的库文件,则会自动生成 libevent_openssl 库;但是如果没有找到 openssl 库文件,则不会生成 libevent_openssl 库文件。

解决这个问题的办法也很简单,重装 openssl:

1. openssl 官网下载 openssl 安装包,解压到本地

$ tar -xvf openssl-1.1.1d

2. 配置 openssl

$ cd openssl-1.1.1d
$ ./config  --prefix=/usr/local --openssldir=/usr/local/openssl

3. 安装 openssl

$ make
$ sudo make install

4. 重新安装 libevent

$ cd libevent-2.1.11-stable
$ ./configure
$ make
$ sudo make install

再重新编译 le-proxy.c 即可。

ps:
参考博客 libevent实现https服务器

比较复杂的 https_client 程序如何编译

剩下一个比较复杂的 https_client 程序的编译:

$ gcc -o https-client https-client.c hostcheck.c openssl_hostname_validation.c -L /usr/local/lib -levent -levent_openssl -lcrypto -lssl

只需要按照 sample 下的 install.am 里面的描述进行填写即可。

https-client 是一个非常好的示例程序,可以仔细阅读,增加自己对于 libevent 的理解。

三、总结

在阅读了 libevent 的官方文档之后,我折腾了整整一个下午,才把 sample 下的示例程序全部编译运行出来。在这过程中遇到了不少问题,也一一在博客中记录了下来。

希望本篇博客能够给你带来一些帮助:)

最后,面对新型肺炎:
中国加油!武汉加油!

发布了269 篇原创文章 · 获赞 361 · 访问量 93万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章