Linux网络编程(七)-第三方库-Libevent01:安装Libevent【Ubuntu20.04】

朴灿烈づ我的快乐病毒、 2023-09-25 12:22 144阅读 0赞

一、安装

验证是否已经安装Libevent

  1. [weblogic@localhost opt]$ ls -al /usr/lib | grep libevent

1.下载

下载地址:
libevent

2.解压文件

  1. [root@localhost opt]# tar -zxvf libevent-2.1.12-stable.tar.gz

3.创建lib文件夹

  1. /usr/local/libevent

4.配置

检测安装环境,例如内存空间是否足够,生成makefile文件。

4.1 配置时不指定安装目录

  1. [root@localhost libevent-2.1.8-stable]# ./configure
  • 将头文件安装在“/usr/local/include”中;

    64aae54dc10e4d77bfa7f6a510c8fe16.png

  • 将库文件放在“/usr/local/lib”中;

    a8a25707ebf84b02bdbeaa7f97f94509.png

4.2 配置时指定安装目录

可以指定具体路径,这样安装的时候,将统一安装到指定路径 例如:./configure —prefix=/usr/local/libevent:

  • 这样的好处是以后打包安装好的文件方便;
  • 不好的地方是由于安装的目录有可能不是系统头文件或库文件的目录,使用的时候需要增加gcc选项来包含头文件路径和库文件路径,以及需要解决动态库不能加载的问题;

    [root@localhost libevent-2.1.8-stable]# ./configure -prefix=/usr/local/libevent

5.编译

生成.o文件和可执行文件

  1. [root@localhost libevent-2.1.8-stable]# make

6.安装

将必要的资源安装到系统的指定目录

  1. [root@localhost libevent-2.1.8-stable]# make install

二、libevent安装错误及解决方式

第1~3步就不用说了,常规准备步骤而已,问题出在第4步配置的时候,此时出现错误:

configure: error: openssl is a must but can not be found. You should add the directory containing ‘openssl.pc’ to the ‘PKG_CONFIG_PATH’ environment variable, or set ‘CFLAGS’ and ‘LDFLAGS’ directly for openssl, or use `–disable-openssl’ to disable support for openssl encryption

解决方式:ubuntu 平台安装 libssl-dev

libssl-dev安装步骤

  1. Update the package index:

    1. # sudo apt-get update
  2. Install libssl-dev deb package:

    1. # sudo apt-get install libssl-dev

三、头文件、库文件(libevent-2.1.12-stable.tar.gz)

  1. libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/sbin" ldconfig -n /usr/local/libevent/lib
  2. ----------------------------------------------------------------------
  3. Libraries have been installed in:
  4. /usr/local/libevent/lib
  5. If you ever happen to want to link against installed libraries
  6. in a given directory, LIBDIR, you must either use libtool, and
  7. specify the full pathname of the library, or use the '-LLIBDIR'
  8. flag during linking and do at least one of the following:
  9. - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
  10. during execution
  11. - add LIBDIR to the 'LD_RUN_PATH' environment variable
  12. during linking
  13. - use the '-Wl,-rpath -Wl,LIBDIR' linker flag
  14. - have your system administrator add LIBDIR to '/etc/ld.so.conf'
  15. See any operating system documentation about shared libraries for
  16. more information, such as the ld(1) and ld.so(8) manual pages.
  17. ----------------------------------------------------------------------
  18. /usr/bin/mkdir -p '/usr/local/libevent/include'
  19. /usr/bin/install -c -m 644 include/evdns.h include/event.h include/evhttp.h include/evrpc.h include/evutil.h '/usr/local/libevent/include'
  20. /usr/bin/mkdir -p '/usr/local/libevent/include/event2'
  21. /usr/bin/install -c -m 644 include/event2/buffer.h include/event2/buffer_compat.h include/event2/bufferevent.h include/event2/bufferevent_compat.h include/event2/bufferevent_struct.h include/event2/dns.h include/event2/dns_compat.h include/event2/dns_struct.h include/event2/event.h include/event2/event_compat.h include/event2/event_struct.h include/event2/http.h include/event2/http_compat.h include/event2/http_struct.h include/event2/keyvalq_struct.h include/event2/listener.h include/event2/rpc.h include/event2/rpc_compat.h include/event2/rpc_struct.h include/event2/tag.h include/event2/tag_compat.h include/event2/thread.h include/event2/util.h include/event2/visibility.h include/event2/bufferevent_ssl.h '/usr/local/libevent/include/event2'
  22. /usr/bin/mkdir -p '/usr/local/libevent/include/event2'
  23. /usr/bin/install -c -m 644 include/event2/event-config.h '/usr/local/libevent/include/event2'
  24. /usr/bin/mkdir -p '/usr/local/libevent/lib/pkgconfig'
  25. /usr/bin/install -c -m 644 libevent.pc libevent_core.pc libevent_extra.pc libevent_pthreads.pc libevent_openssl.pc '/usr/local/libevent/lib/pkgconfig'
  26. make[2]: Leaving directory '/home/libevent-2.1.12-stable'
  27. make[1]: Leaving directory '/home/libevent-2.1.12-stable'
  28. root@iZm5e9phbzdxx0lysrv9t2Z:/home/libevent-2.1.12-stable#

如果在配置阶段没有指定安装目录,则

  • 头文件目录”:/usr/local/include
  • ”的路径:/usr/local/lib

如果在配置阶段没有指定安装目录,例如:./configure —prefix=/usr/local/libevent,则

  • 头文件目录”:/usr/local/libevent/include
  • ”的路径:/usr/local/libevent/lib

添加动态链接库:

  1. root@iZm5e9phbzdxx0lysrv9t2Z:/home/libevent-2.1.12-stable# export LD_LIBRARY_PATH=/usr/local/libevent/lib

三、测试是否安装成功

cd sample ,进入安装文件夹的samle目录,随便测试一个demo,这里测试helloworld.c。

  1. /*
  2. This example program provides a trivial server program that listens for TCP
  3. connections on port 9995. When they arrive, it writes a short message to
  4. each client connection, and closes each connection once it is flushed.
  5. Where possible, it exits cleanly in response to a SIGINT (ctrl-c).
  6. */
  7. #include <string.h>
  8. #include <errno.h>
  9. #include <stdio.h>
  10. #include <signal.h>
  11. #ifndef _WIN32
  12. #include <netinet/in.h>
  13. # ifdef _XOPEN_SOURCE_EXTENDED
  14. # include <arpa/inet.h>
  15. # endif
  16. #include <sys/socket.h>
  17. #endif
  18. #include <event2/bufferevent.h>
  19. #include <event2/buffer.h>
  20. #include <event2/listener.h>
  21. #include <event2/util.h>
  22. #include <event2/event.h>
  23. static const char MESSAGE[] = "Hello, World!\n";
  24. static const int PORT = 9995;
  25. static void listener_cb(struct evconnlistener *, evutil_socket_t,
  26. struct sockaddr *, int socklen, void *);
  27. static void conn_writecb(struct bufferevent *, void *);
  28. static void conn_eventcb(struct bufferevent *, short, void *);
  29. static void signal_cb(evutil_socket_t, short, void *);
  30. int
  31. main(int argc, char **argv)
  32. {
  33. struct event_base *base;
  34. struct evconnlistener *listener;
  35. struct event *signal_event;
  36. struct sockaddr_in sin = {0};
  37. #ifdef _WIN32
  38. WSADATA wsa_data;
  39. WSAStartup(0x0201, &wsa_data);
  40. #endif
  41. base = event_base_new();
  42. if (!base) {
  43. fprintf(stderr, "Could not initialize libevent!\n");
  44. return 1;
  45. }
  46. sin.sin_family = AF_INET;
  47. sin.sin_port = htons(PORT);
  48. listener = evconnlistener_new_bind(base, listener_cb, (void *)base,
  49. LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
  50. (struct sockaddr*)&sin,
  51. sizeof(sin));
  52. if (!listener) {
  53. fprintf(stderr, "Could not create a listener!\n");
  54. return 1;
  55. }
  56. signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
  57. if (!signal_event || event_add(signal_event, NULL)<0) {
  58. fprintf(stderr, "Could not create/add a signal event!\n");
  59. return 1;
  60. }
  61. event_base_dispatch(base);
  62. evconnlistener_free(listener);
  63. event_free(signal_event);
  64. event_base_free(base);
  65. printf("done\n");
  66. return 0;
  67. }
  68. static void
  69. listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
  70. struct sockaddr *sa, int socklen, void *user_data)
  71. {
  72. struct event_base *base = user_data;
  73. struct bufferevent *bev;
  74. bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
  75. if (!bev) {
  76. fprintf(stderr, "Error constructing bufferevent!");
  77. event_base_loopbreak(base);
  78. return;
  79. }
  80. bufferevent_setcb(bev, NULL, conn_writecb, conn_eventcb, NULL);
  81. bufferevent_enable(bev, EV_WRITE);
  82. bufferevent_disable(bev, EV_READ);
  83. bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
  84. }
  85. static void
  86. conn_writecb(struct bufferevent *bev, void *user_data)
  87. {
  88. struct evbuffer *output = bufferevent_get_output(bev);
  89. if (evbuffer_get_length(output) == 0) {
  90. printf("flushed answer\n");
  91. bufferevent_free(bev);
  92. }
  93. }
  94. static void
  95. conn_eventcb(struct bufferevent *bev, short events, void *user_data)
  96. {
  97. if (events & BEV_EVENT_EOF) {
  98. printf("Connection closed.\n");
  99. } else if (events & BEV_EVENT_ERROR) {
  100. printf("Got an error on the connection: %s\n",
  101. strerror(errno));/*XXX win32*/
  102. }
  103. /* None of the other events can happen here, since we haven't enabled
  104. * timeouts */
  105. bufferevent_free(bev);
  106. }
  107. static void
  108. signal_cb(evutil_socket_t sig, short events, void *user_data)
  109. {
  110. struct event_base *base = user_data;
  111. struct timeval delay = { 2, 0 };
  112. printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
  113. event_base_loopexit(base, &delay);
  114. }

gcc helloworld.c -o helloworld //error

此时会报错,因为需要加入libevent库。即完整的命令为

1、如果在配置阶段没有指定安装目录

  1. gcc helloworld.c -o helloworld -l event //去掉lib和后缀.so(动态库)就是库名.

2、如果在配置阶段指定了安装目录,例如:./configure —prefix=/usr/local/libevent,则

  1. gcc helloworld.c -o helloworld -I /usr/local/libevent/include/ -L /usr/local/libevent/lib -l event //去掉lib和后缀.so(动态库)就是库名.

其中:

  • “-I” 参数后面的路径指定头文件路径(/usr/local/libevent/include);
  • “-L”参数后面的路径指定了库文件的路径(/usr/local/libevent/lib);

3、启动服务端

  1. root@iZm5e9phbzdxx0lysrv9t2Z:/home/libevent-2.1.12-stable/sample# ls
  2. dns-example hello-world http-connect.c https_client-openssl_hostname_validation.o le-proxy.c signal-test.o
  3. dns-example.c hello-world.c http-connect.o http-server le_proxy-le-proxy.o time-test
  4. dns-example.o hello-world.o https-client http-server.c openssl_hostname_validation.c time-test.c
  5. event-read-fifo hostcheck.c https-client.c http-server.o openssl_hostname_validation.h time-test.o
  6. event-read-fifo.c hostcheck.h https_client-hostcheck.o include.am signal-test
  7. event-read-fifo.o http-connect https_client-https-client.o le-proxy signal-test.c
  8. root@iZm5e9phbzdxx0lysrv9t2Z:/home/libevent-2.1.12-stable/sample# ./hello-world

4、客户端测试

使用下面命令模拟客户端连接到服务端

  1. nc 127.0.0.1 9995 //libevent默认端口

至此,libevent已经成功安装完成。

如果是使用Makelist,同样的也需要指定头文件目录和链接库目录,如下:

  1. cmake_minimum_required(VERSION 3.12)
  2. project(mytest)
  3. set(CMAKE_CXX_STANDARD 14)
  4. include_directories(/usr/local/libevent/include) #指定头文件搜索路径
  5. LINK_DIRECTORIES(/usr/local/libevent/lib) #指定库文件搜索路径
  6. add_executable(mytest main.cpp)
  7. target_link_libraries(mytest libevent.a) #链接库

四、安装后验证

简单的先编译一个文件 01_getmethods.c

  1. //01_getmethods.c
  2. #include <event.h>
  3. #include <stdio.h>
  4. int main()
  5. {
  6. char ** methods = event_get_supported_methods();//获取libevent后端支持的方法
  7. int i =0;
  8. for(i = 0;methods[i] != NULL ;i++)
  9. {
  10. printf("%s\n",methods[i]);
  11. }
  12. return 0;
  13. }

编译(其中的-levent表示链接第三方的库):

  1. root@iZm5e9phbzdxx0lysrv9t2Z:/home# ll
  2. total 1092
  3. drwxr-xr-x 3 root root 4096 Oct 25 21:23 ./
  4. drwxr-xr-x 20 root root 4096 Oct 25 20:27 ../
  5. -rw-r--r-- 1 root root 289 Oct 23 21:44 01_getmethods.c
  6. drwxr-xr-x 12 1000 1000 4096 Oct 25 20:49 libevent-2.1.12-stable/
  7. -rw-r--r-- 1 root root 1100847 Oct 23 21:40 libevent-2.1.12-stable.tar.gz
  8. root@iZm5e9phbzdxx0lysrv9t2Z:/home# gcc 01_getmethods.c -l event
  9. 01_getmethods.c: In function main’:
  10. 01_getmethods.c:7:23: warning: initialization of char **’ from incompatible pointer type const char **’ [-Wincompatible-pointer-types]
  11. 7 | char ** methods = event_get_supported_methods();//获取libevent后端支持的方法
  12. | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
  13. root@iZm5e9phbzdxx0lysrv9t2Z:/home#

7163baeab9c24e168beff6a3895648ef.png

可以忽略该警告,代表编译完成。默认生成a.out执行文件。

执行:

  1. root@iZm5e9phbzdxx0lysrv9t2Z:/home# ls
  2. 01_getmethods.c a.out libevent-2.1.12-stable libevent-2.1.12-stable.tar.gz
  3. root@iZm5e9phbzdxx0lysrv9t2Z:/home# ./a.out
  4. epoll
  5. poll
  6. select
  7. root@iZm5e9phbzdxx0lysrv9t2Z:/home#

bd0dc2ad67164e74962e40e3f78a0df0.png

同时也能看到libevent在当前主机上后端支持的多路IO方法。

  1. #include <event.h>
  2. #include <stdio.h>
  3. int main()
  4. {
  5. char ** methods = event_get_supported_methods();//获取libevent后端支持的方法
  6. int i =0;
  7. for(i = 0;methods[i] != NULL ;i++)
  8. {
  9. printf("%s\n",methods[i]);
  10. }
  11. struct event_base * base = event_base_new();
  12. printf("\nlibevent在当前主机上后端支持的多路IO方法:%s\n",event_base_get_method(base));
  13. return 0;
  14. }
  15. root@iZm5e9phbzdxx0lysrv9t2Z:/home# ls
  16. 01_getmethods.c a.out libevent-2.1.12-stable libevent-2.1.12-stable.tar.gz
  17. root@iZm5e9phbzdxx0lysrv9t2Z:/home# ./a.out
  18. epoll
  19. poll
  20. select
  21. libevent在当前主机上后端支持的多路IO方法:epoll
  22. root@iZm5e9phbzdxx0lysrv9t2Z:/home#

6、利用libevent创建一个简单的TCP服务器

  1. /*
  2. This exmple program provides a trivial server program that listens for TCP
  3. connections on port 9995. When they arrive, it writes a short message to
  4. each client connection, and closes each connection once it is flushed.
  5. Where possible, it exits cleanly in response to a SIGINT (ctrl-c).
  6. */
  7. #include <string.h>
  8. #include <errno.h>
  9. #include <stdio.h>
  10. #include <signal.h>
  11. #ifndef WIN32
  12. #include <netinet/in.h>
  13. # ifdef _XOPEN_SOURCE_EXTENDED
  14. # include <arpa/inet.h>
  15. # endif
  16. #include <sys/socket.h>
  17. #endif
  18. #include <event2/bufferevent.h>
  19. #include <event2/buffer.h>
  20. #include <event2/listener.h>
  21. #include <event2/util.h>
  22. #include <event2/event.h>
  23. static const char MESSAGE[] = "Hello, World!\n";
  24. static const int PORT = 9995;
  25. static void conn_readcb(struct bufferevent *bev, void *user_data);
  26. static void listener_cb(struct evconnlistener *, evutil_socket_t,
  27. struct sockaddr *, int socklen, void *);
  28. static void conn_writecb(struct bufferevent *, void *);
  29. static void conn_eventcb(struct bufferevent *, short, void *);
  30. static void signal_cb(evutil_socket_t, short, void *);
  31. int
  32. main(int argc, char **argv)
  33. {
  34. struct event_base *base;
  35. struct evconnlistener *listener;
  36. struct event *signal_event;
  37. struct sockaddr_in sin;
  38. #ifdef WIN32
  39. WSADATA wsa_data;
  40. WSAStartup(0x0201, &wsa_data);
  41. #endif
  42. base = event_base_new();//创建event_base根节点
  43. if (!base) {
  44. fprintf(stderr, "Could not initialize libevent!\n");
  45. return 1;
  46. }
  47. memset(&sin, 0, sizeof(sin));
  48. sin.sin_family = AF_INET;
  49. sin.sin_port = htons(PORT);
  50. //创建链接侦听器
  51. listener = evconnlistener_new_bind(base, listener_cb, (void *)base,
  52. LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
  53. (struct sockaddr*)&sin,
  54. sizeof(sin));
  55. if (!listener) {
  56. fprintf(stderr, "Could not create a listener!\n");
  57. return 1;
  58. }
  59. //创建信触发的节点
  60. signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
  61. //将信号节点上树
  62. if (!signal_event || event_add(signal_event, NULL)<0) {
  63. fprintf(stderr, "Could not create/add a signal event!\n");
  64. return 1;
  65. }
  66. event_base_dispatch(base);//循环监听
  67. evconnlistener_free(listener);//释放链接侦听器
  68. event_free(signal_event);//释放信号节点
  69. event_base_free(base);//释放event_base根节点
  70. printf("done\n");
  71. return 0;
  72. }
  73. static void
  74. listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
  75. struct sockaddr *sa, int socklen, void *user_data)
  76. {
  77. struct event_base *base = user_data;
  78. struct bufferevent *bev;
  79. //将fd上树
  80. //新建一个buffervent节点
  81. bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
  82. if (!bev) {
  83. fprintf(stderr, "Error constructing bufferevent!");
  84. event_base_loopbreak(base);
  85. return;
  86. }
  87. //设置回调
  88. bufferevent_setcb(bev, conn_readcb, conn_writecb, conn_eventcb, NULL);
  89. bufferevent_enable(bev, EV_WRITE | EV_READ);//设置写事件使能
  90. //bufferevent_disable(bev, EV_READ);//设置读事件非使能
  91. bufferevent_write(bev, MESSAGE, strlen(MESSAGE));//给cfd发送消息 helloworld
  92. }
  93. static void conn_readcb(struct bufferevent *bev, void *user_data)
  94. {
  95. char buf[1500]="";
  96. int n = bufferevent_read(bev,buf,sizeof(buf));
  97. printf("%s\n",buf);
  98. bufferevent_write(bev, buf,n);//给cfd发送消息
  99. }
  100. static void
  101. conn_writecb(struct bufferevent *bev, void *user_data)
  102. {
  103. struct evbuffer *output = bufferevent_get_output(bev);//获取缓冲区类型
  104. if (evbuffer_get_length(output) == 0) {
  105. // printf("flushed answer\n");
  106. // bufferevent_free(bev);//释放节点 自动关闭
  107. }
  108. }
  109. static void
  110. conn_eventcb(struct bufferevent *bev, short events, void *user_data)
  111. {
  112. if (events & BEV_EVENT_EOF) {
  113. printf("Connection closed.\n");
  114. } else if (events & BEV_EVENT_ERROR) {
  115. printf("Got an error on the connection: %s\n",
  116. strerror(errno));/*XXX win32*/
  117. }
  118. /* None of the other events can happen here, since we haven't enabled
  119. * timeouts */
  120. bufferevent_free(bev);
  121. }
  122. static void
  123. signal_cb(evutil_socket_t sig, short events, void *user_data)
  124. {
  125. struct event_base *base = user_data;
  126. struct timeval delay = { 2, 0 };
  127. printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
  128. event_base_loopexit(base, &delay);//退出循环监听
  129. }

#

01libevent库的下载与安装并且测试是否安装成功_Mango酱的博客-CSDN博客_libevent下载

libssl-dev安装步骤_WangEason1985的博客-CSDN博客_windows安装libssl-dev

1 Libevent官方 · libevent深入浅出

linux安装 Libevent安装和使用_东山富哥的博客-CSDN博客_libevent安装

Libenent: configure: error: openssl is a must but can not be found._贪心的鬼的博客-CSDN博客

linux无法编译libevent,一直报错,但是我有装openssl - SegmentFault 思否

记录关于libevent安装错误:configure: error: openssl is a must but can not be found. You should add the direct_youngchanlll的博客-CSDN博客_安装libevent报错

发表评论

表情:
评论列表 (有 0 条评论,144人围观)

还没有评论,来说两句吧...

相关阅读