Linux下编译libevent的指导可以参考《4、《Libevent中文帮助文档》学习笔记4:Linux下编译libevent》,完成编译、安装,生成so库后,其他程序即可依赖libevent的so库,使用libevent的功能。

由于没有通过prefix指定安装路径,因此库文件默认安装在/usr/local/lib下,头文件在/usr/local/include下,如下所示:

如图可以看出,libevent的so库存在软链接现象。

集成libevent的源码如下:

/*For sockaddr_in*/
#include <netinet/in.h>
/*For socket functions*/
#include <sys/socket.h>
/*For fcntl*/
#include <fcntl.h>
#include <event2/event.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define MAX_LINE 16384void do_read(evutil_socket_t fd, short events, void*arg);
void do_write(evutil_socket_t fd, short events, void*arg);char rot13_char(char c)
{/* We don’t want to use isalpha here; setting the locale change which characters are considered alphabetical.*/if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M')){return c + 13;}else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z')){return c - 13;}else{return c;}
}struct fd_state
{char buffer[MAX_LINE];size_t buffer_used;size_t n_written;size_t write_upto;struct event* read_event;struct event* write_event;
};struct fd_state* alloc_fd_state(struct event_base* base, evutil_socket_t fd)
{struct fd_state* state = malloc(sizeof(struct fd_state));if (!state) return NULL;state->read_event = event_new(base, fd, EV_READ | EV_PERSIST, do_read, state);if (!state->read_event){free(state); return NULL;}state->write_event = event_new(base, fd, EV_WRITE | EV_PERSIST, do_write, state);if (!state->write_event){event_free(state->read_event);free(state);return NULL;}state->buffer_used = state->n_written = state->write_upto = 0;assert(state->write_event);return state;
}void free_fd_state(struct fd_state* state)
{event_free(state->read_event);event_free(state->write_event);free(state);
}void do_read(evutil_socket_t fd, short events, void*arg)
{struct fd_state*state = arg;char buf[1024]; int i; ssize_t result;while (1){assert(state->write_event);result = recv(fd, buf, sizeof(buf), 0);if(result <= 0)break;for (i = 0; i < result; ++i){if (state->buffer_used < sizeof(state->buffer))state->buffer[state->buffer_used++] = rot13_char(buf[i]);if (buf[i] == '\n'){assert(state->write_event);event_add(state->write_event, NULL);state->write_upto = state->buffer_used;}}}if (result == 0){free_fd_state(state);}else if (result < 0){if (errno == EAGAIN) // XXXX use evutil macro return ; perror("recv");                 free_fd_state(state);}
} void do_write(evutil_socket_t fd, short events, void*arg)
{struct fd_state*state = arg;while (state->n_written < state->write_upto){ssize_t result = send(fd, state->buffer + state->n_written, state ->write_upto -         state->n_written, 0);if (result < 0){if (errno == EAGAIN) // XXX use evutil macro return ;free_fd_state(state);return;}assert(result != 0);state->n_written += result;}if (state->n_written == state->buffer_used)state->n_written = state->write_upto = state->buffer_used = 1;event_del(state->write_event);
}void do_accept(evutil_socket_t listener, short event, void*arg)
{struct event_base*base = arg;struct sockaddr_storage ss;socklen_t slen =sizeof(ss);int fd = accept(listener, (struct sockaddr*) &ss, &slen);if (fd < 0){// XXXX eagain??perror("accept");}else if (fd > FD_SETSIZE){close(fd); // XXX replace all closes with EVUTIL_CLOSESOCKET}else{struct fd_state*state;evutil_make_socket_nonblocking(fd);state =alloc_fd_state(base, fd);assert(state);/*XXX err */assert(state->write_event);event_add(state->read_event, NULL);}
}void run(void)
{struct event_base* base = event_base_new();if (!base) return;/* 创建socket */struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_addr.s_addr = 0;sin.sin_port = htons(40713);evutil_socket_t listener = socket(AF_INET, SOCK_STREAM, 0);/* 设置为非阻塞 */evutil_make_socket_nonblocking(listener);#ifndef WIN32{int one = 1;setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));}
#endif/* 绑定socket */if (bind(listener, (struct sockaddr*) &sin, sizeof(sin)) < 0){perror("bind");return;}/* 启动监听 */if (listen(listener, 16) < 0){perror("listen");return;}struct event* listener_event = event_new(base, listener, EV_READ | EV_PERSIST, do_accept,(void*)base);/*XXX check it*/event_add(listener_event, NULL);event_base_dispatch(base);
}int main(int c, char**v)
{setvbuf(stdout, NULL, _IONBF, 0);run();return 0;
}

编写完源码后,接下去的工作就是编译。使用如下命令进行编译:

gcc -o server server.c -levent_core

由于libevent安装在/usr/local/lib目录下,因为不需要指定依赖路径,直接指定依赖libevent_core.so即可。

编译成功后,执行如下命令,运行可执行文件sever:

./server

出现如下报错:

./server: error while loading shared libraries: libevent_core-2.1.so.6: cannot open shared object file: No such file or directory

即无法加载可执行文件server的依赖库libevent_core-2.1.so.6,看到这里有点懵了,编译时,指定的依赖库文件明明是libevent_core.so,为什么在这里变为libevent_core-2.1.so.6,猜想可能原因是-levent_core匹配到/usr/local/lib/目录下的libevent_core-2.1.so.6了。但是,无论是libevent_core-2.1.so.6,还是libevent_core.so,都只是一个文件软链接,最终指向的都是libevent_core-2.1.so.6.0.2。

即使server依赖的是libevent_core-2.1.so.6,但是为啥运行报错了?/usr/local/lib目录下是有这个文件的啊?因此,通过如下命令查看server的依赖库信息:

ldd server

依赖库如下所示:

        linux-vdso.so.1 =>  (0x00007ffd4f78b000)
        libevent_core-2.1.so.6 => not found
        libc.so.6 => /lib64/libc.so.6 (0x00007fa2a92b5000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa2a9682000)

发现确实无法加载到libevent_core-2.1.so.6。通过如下命令,查看server的库搜索路径:

LD_DEBUG=libs ./server -v

搜索路径为:

     20398:     find library=libevent_core-2.1.so.6 [0]; searching
     20398:      search cache=/etc/ld.so.cache
     20398:      search path=/lib64/tls/x86_64:/lib64/tls:/lib64/x86_64:/lib64:/usr/lib64/tls/x86_64:/usr/lib64/tls:/usr/lib64/x86_64:/usr/lib64                (system search path)
     20398:       trying file=/lib64/tls/x86_64/libevent_core-2.1.so.6
     20398:       trying file=/lib64/tls/libevent_core-2.1.so.6
     20398:       trying file=/lib64/x86_64/libevent_core-2.1.so.6
     20398:       trying file=/lib64/libevent_core-2.1.so.6
     20398:       trying file=/usr/lib64/tls/x86_64/libevent_core-2.1.so.6
     20398:       trying file=/usr/lib64/tls/libevent_core-2.1.so.6
     20398:       trying file=/usr/lib64/x86_64/libevent_core-2.1.so.6
     20398:       trying file=/usr/lib64/libevent_core-2.1.so.6
     20398:
./server: error while loading shared libraries: libevent_core-2.1.so.6: cannot open shared object file: No such file or directory

发现搜索路径中,并没有/usr/local/lib,自然是无法加载到libevent_core-2.1.so.6。因此,将libevent_core-2.1.so.6拷贝到搜索路径下即可。也可以通过如下命令,为/usr/local/lib/libevent_core-2.1.so.6在/usr/lib64/下创建一个软链接:

ln -s /usr/local/lib/libevent_core-2.1.so.6 /usr/lib64/libevent_core-2.1.so.6

13、《Libevent中文帮助文档》学习笔记13:Linux下集成、运行libevent相关推荐

  1. 【ember zigbee】序章:协议栈相关文档学习笔记

    原文地址:https://blog.csdn.net/tainjau/article/details/90648114 文章目录 写在前面 一.材料出处 二.文档解析 2.1.EZSP Protoco ...

  2. python定义函数的组成部分有_Python文档学习笔记(4)--定义函数

    定义函数 关键字 def 引入函数的定义.其后必须跟有函数名和以括号标明的形式参数列表.组成函数体的语句从下一行开始,且必须缩进. 执行 一个函数会引入一个用于函数的局部变量的新符号表. 因此,在函数 ...

  3. IAM 策略文档学习笔记

    策略文档 IAM 许可策略 附加到确定角色可执行哪些任务的角色.将许可限定为仅角色需要进行的操作,以及仅为进行这些操作角色需要的资源.您可以使用 AWS 管理的或客户创建的 IAM 许可策略 操作:您 ...

  4. w3schools文档学习笔记 - XML

    http://www.w3school.com.cn/xml/xml_syntax.asp 在 XML 中,省略关闭标签是非法的.所有元素都必须有关闭标签 声明不属于XML本身的组成部分.它不是 XM ...

  5. Vue3 文档学习笔记

    vue3学习笔记 setup() 生命周期的与vue2的不同点在:beforeCreated.created都在setup()里进行默认调用,其他的都要写在setup()里面,算做compositio ...

  6. 冰冰学习笔记:Linux下的常用指令

    欢迎各位大佬光临本文章!!! 还请各位大佬提出宝贵的意见,如发现文章错误请联系冰冰,冰冰一定会虚心接受,及时改正. 本系列文章为冰冰学习编程的学习笔记,如果对您也有帮助,还请各位大佬.帅哥.美女点点支 ...

  7. 冰冰学习笔记:Linux下的权限理解

    欢迎各位大佬光临本文章!!! 还请各位大佬提出宝贵的意见,如发现文章错误请联系冰冰,冰冰一定会虚心接受,及时改正. 本系列文章为冰冰学习编程的学习笔记,如果对您也有帮助,还请各位大佬.帅哥.美女点点支 ...

  8. 【Linux学习笔记】Linux下安装Libreoffice

    Linux下安装Libreoffice 一.Libreoffice简介 二.安装 2.1.如果安装过libreoffice,需要先卸载 2.2.下载libreoffice 2.3.将下载的文件放到/u ...

  9. Django1.10文档学习笔记二

    创建应用 1 创建project Django-admin startproject mysite 自动创建目录结构: mysite/    #项目容器 Manage.py    #命令行工具 mys ...

最新文章

  1. click和blur 冲突???
  2. 提高jQuery执行效率
  3. 【电商】几种电商模式及特点
  4. MVC模式 在Java Web应用程序中的实现
  5. [笔试题]交换两个数不使用第三方变量 深入理解按位异或运算符
  6. 程序员过关斩将--快速迁移10亿级数据
  7. GeeksForGeeks 翻译计划 | ApacheCN
  8. linux定时备份Mysql
  9. Python黑魔法 --- 异步IO( asyncio) 协程
  10. IPEX: SMA/UFL/IPEX/IPX接头,各代区别
  11. espritcam后处理教学_Master CAM 后置处理文件及其设定方法详细说明
  12. Swift高仿iOS网易云音乐Moya+RxSwift+Kingfisher+MVC+MVVM
  13. 抢红包算法 c语言,微信红包的随机算法是怎样实现的?
  14. 【数据分享】1997-2016年全国大部分地级市气温降水数据
  15. 2021 上半年软考软件设计师真题完整版
  16. 关于瀚高数据库的适配
  17. Pandas数据结构
  18. edge浏览器打开html文件路径被拆分,Win10默认浏览器被强制修改为Edge的两种解决方法...
  19. 联想计算机怎么添加打印机,电脑和联想打印机连接不上怎么办啊
  20. Interceptor for {http://admin.ws…thrown exception, unwinding now java.lang.NullPointerException

热门文章

  1. rndis模块 linux,openwrt 19.7 驱动添加rndis模式4G模块
  2. 领带的10种打法(男人必看)
  3. 安卓拨号界面查询*#代码大全(由于最近普通用户爱玩这些黑科技,于是在网上找了些)
  4. OSChina 周五乱弹 ——越污的人颜值越高 不信看图!
  5. SAP_增强案例_MB51(物料凭证清单)新增客户化字段
  6. 量子宇宙(比肩《时间简史》,世界公认优秀的量子力学入门书)
  7. BDD、KITTI、Cityscapes和Foggy Cityscapes百度云链接
  8. 三星s10刷android原生,三星S10 S10+ 国行版 安卓9 完美ROOT 精简稳定 丰富高级设置 Magisk 省电刷机包...
  9. 软件、应用_SDK相关
  10. 云村,网易云音乐的扛把子?