在我的昨天的博文《[原]我在Windows环境下的首个Libevent测试实例》中介绍了在Windows环境下如何编译一个echo server例子。今天我又试了一下在Linux环境中编译这个例子,遇到了一些问题,学习到了很多知识。这里也顺便记一下,增强一下理解。直接上代码:

 #include <iostream>
#include <sys/socket.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
using namespace std; void do_accept(evutil_socket_t listener, short event, void *arg);
void read_cb(struct bufferevent *bev, void *arg);
void error_cb(struct bufferevent *bev, short event, void *arg);
void write_cb(struct bufferevent *bev, void *arg); int main()
{
int ret = ;
evutil_socket_t listener;
listener = socket(AF_INET, SOCK_STREAM, );
evutil_make_listen_socket_reuseable(listener); struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ;
sin.sin_port = htons();
if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) < )
{
cout << "bind error" << endl;
return -;
}
if (listen(listener, ) < )
{
cout << "listen error" << endl;
return -;
}
cout << "Listening..." << endl; evutil_make_socket_nonblocking(listener);
struct event_base* base = event_base_new();
if (NULL == base)
{
cout << "event_base_new error" << endl;
return -;
} struct event* listen_event = event_new(base, listener, EV_READ | EV_PERSIST, do_accept, (void*)base);
event_add(listen_event, NULL);
event_base_dispatch(base);
event_base_free(base); cout << "Done!" << endl;
return ;
} void do_accept(evutil_socket_t listener, short event, void *arg)
{
struct event_base* base = (struct event_base *)arg;
struct sockaddr_in sin;
socklen_t slen = sizeof sin;
evutil_socket_t fd = accept(listener, (struct sockaddr *)&sin, &slen);
if (fd < )
{
cout << "accept error" << endl;
return;
}
//if (fd > FD_SETSIZE)
//{
// cout << "accept����fd����FD_SETSIZE����" << endl;
// return;
//}
cout << "accept:fd=" << fd << endl; struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, read_cb, NULL, error_cb, arg);
bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);
} void read_cb(struct bufferevent *bev, void *arg)
{
#define MAX_LINE 256
char szLine[MAX_LINE + ];
evutil_socket_t fd = bufferevent_getfd(bev); int n = ;
while (n = bufferevent_read(bev, szLine, MAX_LINE), n > )
{
szLine[n] = '\0';
cout << "Read Line:" << szLine << endl;
bufferevent_write(bev, szLine, n);
}
} void write_cb(struct bufferevent *bev, void *arg)
{ } void error_cb(struct bufferevent *bev, short event, void *arg)
{
evutil_socket_t fd = bufferevent_getfd(bev);
cout << "error:fd=" << fd << endl;
if (event & BEV_EVENT_TIMEOUT)
{
cout << "Time out!" << endl;
}
else if (event & BEV_EVENT_EOF)
{
cout << "EOF!" << endl;
}
else if (event & BEV_EVENT_ERROR)
{
cout << "Error!" << endl;
}
bufferevent_free(bev);
}

  这个代码与昨天的博文中的代码基本一致,不同的地方在于:

(1)头文件不一样。Linux环境下的头文件默认都是在/usr/include中包含的,如果*.h文件在子目录中,则需要加上子目录的名字;

(2)结构体不同。Windows环境下声明了SOCKADD_IN、SOCKADD、ADDR_ANY等宏,这在Linux环境下是没有的。

  到了编译的时候,由于很久没有接触Linux,所以几乎都不会编译了。直接利用g++编译的时候,出现错误提示说找不到event.h头文件,诧异了一下后我明白了,应该是/usr/include目录中没有相应的头文件。但是我用rpm -qa | grep libevent查看时,却发现系统中已经安装了:

[xiaoku@localhost workspace]$ rpm -qa | grep libevent
libevent-2.0.-.fc20.x86_64

  那为什么没有头文件呢?原来,Fedora中默认只是支持了该链接库,却没有提供利用该函数库进行开发的接口,需要安装devel包才行,我以前还一直纳闷devel包是做什么用的呢。利用yum install libevent*就能安装开发包了,安装完之后,我发现我的/usr/include目录下多了一个event2子目录和event.h头文件。再查看就是这样的:

[xiaoku@localhost workspace]$ rpm -qa | grep libevent
libevent-2.0.-.fc20.x86_64
libevent-devel-2.0.-.fc20.x86_64
[xiaoku@localhost workspace]$ ll /usr/include/ | grep event
drwxr-xr-x. root root 9月 : event2
-rw-r--r--. root root 8月 event.h

  至此,libevent的开发环境算是搭建好了,下面开始编译吧:

[xiaoku@localhost workspace]$ g++ main.cpp -o echoServer -levent

  注意最后的-levent很重要,表示要链接event静态函数库。如果没有这一句,那么整个链接将会出错,类似于下面的结局:

[xiaoku@localhost workspace]$ g++ main.cpp -o echoServer
/tmp/ccFk4bSL.o:在函数‘main’中:
main.cpp:(.text+0x2c):对‘evutil_make_listen_socket_reuseable’未定义的引用
main.cpp:(.text+0xec):对‘evutil_make_socket_nonblocking’未定义的引用
main.cpp:(.text+0xf1):对‘event_base_new’未定义的引用
main.cpp:(.text+0x13f):对‘event_new’未定义的引用
main.cpp:(.text+0x154):对‘event_add’未定义的引用
main.cpp:(.text+0x160):对‘event_base_dispatch’未定义的引用
main.cpp:(.text+0x16c):对‘event_base_free’未定义的引用
/tmp/ccFk4bSL.o:在函数‘do_accept(int, short, void*)’中:
main.cpp:(.text+0x22e):对‘bufferevent_socket_new’未定义的引用
main.cpp:(.text+0x254):对‘bufferevent_setcb’未定义的引用
main.cpp:(.text+0x265):对‘bufferevent_enable’未定义的引用
/tmp/ccFk4bSL.o:在函数‘read_cb(bufferevent*, void*)’中:
main.cpp:(.text+0x28f):对‘bufferevent_getfd’未定义的引用
main.cpp:(.text+0x2f5):对‘bufferevent_write’未定义的引用
main.cpp:(.text+0x313):对‘bufferevent_read’未定义的引用
/tmp/ccFk4bSL.o:在函数‘error_cb(bufferevent*, short, void*)’中:
main.cpp:(.text+0x357):对‘bufferevent_getfd’未定义的引用
main.cpp:(.text+0x408):对‘bufferevent_free’未定义的引用
collect2: 错误:ld 返回  

[原]在Fedora中编译Libevent测试实例的更多相关文章

  1. [原]我在Windows环境下的首个Libevent测试实例

    libevent对Windows环境也有很好的支持,不过初次学习和编译libevent简单实例,总是有一些陌生感的,只有成功编译并测试了一个实例,才会有恍然大悟的感觉.下面将要讲到的一个实例是我从网上 ...

  2. Confluence 6 从生产环境中恢复一个测试实例

    请参考 Restoring a Test Instance from Production 页面中的内容获得更多完整的说明. 很多 Confluence 的管理员将会使用生产实例运行完整数据和服务的 ...

  3. 在Azure DevOps Server (TFS)的流水线中编译和测试Xcode移动应用(iPhone)

    概述 Xcode是开发基于苹果macOS系统的桌面应用和移动应用的主要IDE工具.使用Azure DevOps Server (原名TFS)系统中的pipelines流水线功能,可以方便的集成Xcod ...

  4. (原)Ubuntu16中编译caffe

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5797526.html 参考网址: http://caffe.berkeleyvision.org/in ...

  5. sql中with as测试实例

    一.使用场景 1.多处使用才有必要2.一方面减少代码数量便于理解维护3.一方面跟代码一样一次计算到处用 二.实例(本处示例仅为测试,实际用join比较好) 1.不使用with as 2.使用with ...

  6. (原)ubuntu16中编译boost1.61.0库

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5797940.html 参考网址: http://www.boost.org/doc/libs/1_61 ...

  7. WinForm中 Asp.Net Signalr消息推送测试实例

    p{ text-align:center; } blockquote > p > span{ text-align:center; font-size: 18px; color: #ff0 ...

  8. Windows 上静态编译 Libevent 2.0.10 并实现一个简单 HTTP 服务器(图文并茂,还有实例下载)

    [文章作者:张宴 本文版本:v1.0 最后修改:2011.03.30 转载请注明原文链接:http://blog.s135.com/libevent_windows/] 本文介绍了如何在 Window ...

  9. android studio 使用 jni 编译 opencv 完整实例 之 图像边缘检测!从此在andrid中自由使用 图像匹配、识别、检测

    目录: 1,过程感慨: 2,运行环境: 3,准备工作: 4,编译 .so 5,遇到的关键问题及其解决方法 6,实现效果截图. (原创:转载声明出处:http://www.cnblogs.com/lin ...

随机推荐

  1. Xen虚拟机磁盘镜像模板制作(二)—Windows Server 2008(2012)

    在<Xen虚拟机磁盘镜像模板制作(一)—Windows Server 2008(2012)>一文中,我们已经成功制作出了Windows Server磁盘镜像.下面我们说明下如何通过它来生成 ...

  2. Eclipse Java 开发平台实用技巧

    前言 在使用Eclipse开发Java程序的使用,有很多实用的技巧,能大大提高开发效率. 本文将介绍一部分技巧.更多的心得还得在具体项目中慢慢掌握,熟悉. 初始设定 这些具体的设置方法这里不说,网上很 ...

  3. CentOS7上安装和使用Docker

    导读 Docker 是一个开源工具,它可以让创建和管理 Linux 容器变得简单,容器就像是轻量级的虚拟机,并且可以以毫秒级的速度来启动或停止.在本篇文章中我们将教你如何在 CentOS 7.x 中安 ...

  4. dede首页调用栏目内容_{dede:field.content/}首页调用

    如何将已经做成单页的栏目内容调用到首页来. 常用的需要调到首页来的单页内容,比如公司简介.联系我们等内容,我们在首页可能都要进行展现.通过常规的方式,包括查阅dede官方论坛资料,都找不到比较合适的答 ...

  5. android:clipToPadding 和 android:clipChildren 解决ListView设置padding后 padding不跟随改动

    clipToPadding就是说控件的绘制区域是否在padding里面的,true的情况下如果你设置了padding那么绘制的区域就往里 缩, clipChildren是指子控件是否超过padding ...

  6. leetcode 140. Word Break II ----- java

    Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each ...

  7. 3-4 rpm包查询

    概述:yum不能查询已经安装好的rpm包, 就算采用了yum来进行安装,查询方法还是依赖rpm包的查询, 因此rpm包的查询十分常用和重要 1.查询是否安装 <1>rpm -q 包名(不是 ...

  8. about JNI

    1.Java对C/C++事件处理的封装JIT(Just in Time.Java语言的原动态编译技术) 大多数的游戏引擎都是使用可移植的C语言开发的,然后通过简单的封装以适应特殊的平台. 2.Andr ...

  9. [poj 3691]DNA repair

    好久没刷 poj 了,今天练习 AC 自动机时去水了一发喵~ 在 poj 上 A 题的感觉并没有 BZOJ 上那么愉悦,准确的说是痛不欲生 真是应了那句老话,你再慢也有比你慢的,你再快也有比你快的…… ...

  10. 配置Apache将自己的电脑做服务器使局域网内的电脑访问自己的主机

    很多的朋友都想把自己的电脑打造为服务器使别人能够访问.比如说你自己写了一网站,只能自己通过localhost访问或127.0.0.1访问.但是怎么让别人的电脑也能访问呢?来看看自己写的网站.现在我来讲 ...