zoukankan      html  css  js  c++  java
  • [原]在Fedora中编译Libevent测试实例

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

      1 #include <iostream>
      2 #include <sys/socket.h>
      3 #include <event2/event.h>    
      4 #include <event2/bufferevent.h>
      5 using namespace std;
      6 
      7 void do_accept(evutil_socket_t listener, short event, void *arg);
      8 void read_cb(struct bufferevent *bev, void *arg);
      9 void error_cb(struct bufferevent *bev, short event, void *arg);
     10 void write_cb(struct bufferevent *bev, void *arg);
     11 
     12 int main()
     13 {
     14     int ret = 0;
     15     evutil_socket_t listener;
     16     listener = socket(AF_INET, SOCK_STREAM, 0);
     17     evutil_make_listen_socket_reuseable(listener);
     18 
     19     struct sockaddr_in sin;
     20     sin.sin_family = AF_INET;
     21     sin.sin_addr.s_addr = 0;
     22     sin.sin_port = htons(6789);
     23     if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) < 0)
     24     {
     25         cout << "bind error" << endl;
     26         return -1;
     27     }
     28     if (listen(listener, 32) < 0)
     29     {
     30         cout << "listen error" << endl;
     31         return -1;
     32     }
     33     cout << "Listening..." << endl;
     34 
     35     evutil_make_socket_nonblocking(listener);
     36     struct event_base* base = event_base_new();    
     37     if (NULL == base)
     38     {
     39         cout << "event_base_new error" << endl;
     40         return -1;
     41     }
     42     
     43     struct event* listen_event = event_new(base, listener, EV_READ | EV_PERSIST, do_accept, (void*)base);
     44     event_add(listen_event, NULL);
     45     event_base_dispatch(base);
     46     event_base_free(base);
     47 
     48     cout << "Done!" << endl;
     49     return 0;
     50 }
     51 
     52 void do_accept(evutil_socket_t listener, short event, void *arg)
     53 {
     54     struct event_base* base = (struct event_base *)arg;
     55     struct sockaddr_in sin;
     56     socklen_t slen = sizeof sin;
     57     evutil_socket_t fd = accept(listener, (struct sockaddr *)&sin, &slen);
     58     if (fd < 0)
     59     {
     60         cout << "accept error" << endl;
     61         return;
     62     }
     63     //if (fd > FD_SETSIZE)
     64     //{
     65     //    cout << "accept����fd����FD_SETSIZE����" << endl;
     66     //    return;
     67     //}
     68     cout << "accept:fd=" << fd << endl;
     69 
     70     struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
     71     bufferevent_setcb(bev, read_cb, NULL, error_cb, arg);
     72     bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);
     73 }
     74 
     75 void read_cb(struct bufferevent *bev, void *arg)
     76 {
     77 #define MAX_LINE    256
     78     char szLine[MAX_LINE + 1];
     79     evutil_socket_t fd = bufferevent_getfd(bev);
     80 
     81     int n = 0;
     82     while (n = bufferevent_read(bev, szLine, MAX_LINE), n > 0)
     83     {
     84         szLine[n] = '';
     85         cout << "Read Line:" << szLine << endl;
     86         bufferevent_write(bev, szLine, n);
     87     }
     88 }
     89 
     90 void write_cb(struct bufferevent *bev, void *arg)
     91 {
     92 
     93 }
     94 
     95 void error_cb(struct bufferevent *bev, short event, void *arg)
     96 {
     97     evutil_socket_t fd = bufferevent_getfd(bev);
     98     cout << "error:fd=" << fd << endl;
     99     if (event & BEV_EVENT_TIMEOUT)
    100     {
    101         cout << "Time out!" << endl;
    102     }
    103     else if (event & BEV_EVENT_EOF)
    104     {
    105         cout << "EOF!" << endl;
    106     }
    107     else if    (event & BEV_EVENT_ERROR)
    108     {
    109         cout << "Error!" << endl;
    110     }
    111     bufferevent_free(bev);
    112 }
    View Code

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

    (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.21-3.fc20.x86_64

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

    [xiaoku@localhost workspace]$ rpm -qa | grep libevent
    libevent-2.0.21-3.fc20.x86_64
    libevent-devel-2.0.21-3.fc20.x86_64
    [xiaoku@localhost workspace]$ ll /usr/include/ | grep event
    drwxr-xr-x.  2 root root   4096 9月  23 13:54 event2
    -rw-r--r--.  1 root root   2760 8月  22 2013 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 返回 1 
  • 相关阅读:
    struts2+Hibernate4+spring3+EasyUI环境搭建之四:引入hibernate4以及spring3与hibernate4整合
    struts2+Hibernate4+spring3+EasyUI环境搭建之三:引入sututs2以及spring与sututs2整合
    struts2+Hibernate4+spring3+EasyUI环境搭建之二:搭建spring
    Log4j
    【maven学习】构建maven web项目
    struts2+Hibernate4+spring3+EasyUI环境搭建之一:准备工作
    高版本myeclipse破解以及优化
    Eclipse&Myeclipse安装反编译插件
    Flask源码阅读-第四篇(flaskapp.py)
    Flask源码阅读-第三篇(flask\_compat.py)
  • 原文地址:https://www.cnblogs.com/kuliuheng/p/3988627.html
Copyright © 2011-2022 走看看