一、引言
最近在工作中接触到了 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 下的示例程序全部编译运行出来。在这过程中遇到了不少问题,也一一在博客中记录了下来。
希望本篇博客能够给你带来一些帮助:)
最后,面对新型肺炎:
中国加油!武汉加油!
来源:CSDN
作者:曾经去过跨越一个小时的地方
链接:https://blog.csdn.net/u012814856/article/details/104283474