这一节是安装篇。
Socket网络编程不知不觉已经学了快两个月了。现在是时候找个网络库学学了。搜索了很多关于如何学网络编程的博客和问答。大致都是推荐学一个网络库,至于C++网络库有那么几个,各有各的好处。这里就选这个代码量少了,方便入门,等有一定的基础后,再看看“学之者生,用之着死”的ace或者有可能成为C++标准网络库的boost::asio,这个都是后话了。
CentOS上安装软件最简单的当然是yum安装,我们可爱的libev好像现在还没有,那我们只能通过源码安装了。地址: http://dist.schmorp.de/libev/libev-4.15.tar.gz
1 wget http://dist.schmorp.de/libev/libev-4.15.tar.gz 2 tar -zxf libev-4.15.tar.gz 3 cd libev-4.15 4 ./configure 5 make 6 make install
下面这些是安装信息
1 Libraries have been installed in: 2 /usr/local/lib 3 4 If you ever happen to want to link against installed libraries 5 in a given directory, LIBDIR, you must either use libtool, and 6 specify the full pathname of the library, or use the `-LLIBDIR' 7 flag during linking and do at least one of the following: 8 - add LIBDIR to the `LD_LIBRARY_PATH' environment variable 9 during execution 10 - add LIBDIR to the `LD_RUN_PATH' environment variable 11 during linking 12 - use the `-Wl,-rpath -Wl,LIBDIR' linker flag 13 - have your system administrator add LIBDIR to `/etc/ld.so.conf' 14 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 /bin/mkdir -p '/usr/local/include' 19 /usr/bin/install -c -m 644 ev.h ev++.h event.h '/usr/local/include' 20 /bin/mkdir -p '/usr/local/share/man/man3' 21 /usr/bin/install -c -m 644 ev.3 '/usr/local/share/man/man3'
下面给出一个官方的例子
#include <stdio.h> #include <ev.h> //ev库头文件 //定义一个ev_TYPE 的结构体 ev_io stdin_watcher;//定义一个stdin的观测者 ev_timer timeout_watcher; //所有的watcher的回调函数都有相似的特点 //当stdin有可读的数据时,将会调用下面这个回调函数 static void stdin_cb(EV_P_ ev_io *w,int revents) { puts("stdin ready"); //每一次时间都必须用对应的停止函数,手动的停止其watcher ev_io_stop(EV_A_ w); //这将导致所有嵌套执行的ev_run停止监听 ev_break(EV_A_ EVBREAK_ALL); } //这是一个回调函数,用于定时器回调 static void timeout_cb(EV_P_ ev_timer *w,int revents) { puts("timeout"); //这将导致最早运行的ev_run停止监听 ev_break(EV_A_ EVBREAK_ONE); } int main(int argc,char **args) { //使用一般默认的事件循环 struct ev_loop *loop = EV_DEFAULT; //初始化一个I/O watcher,然后启动它 ev_io_init(&stdin_watcher,stdin_cb,0,EV_READ); ev_io_start(loop,&stdin_watcher); //初始化一个定时器watcher,然后启动它,只有一次,没有重复的5.5秒定时 ev_timer_init(&timeout_watcher,timeout_cb,5.5,0); ev_timer_start(loop,&timeout_watcher); //这里等待时间出发 ev_run(loop,0); //撤销监听退出程序 return 0; }
编译 gcc server.c -lev -o server 就这样是可以编译通过的,但是执行就说找不到一个libev的库。看了一下上面的安装信息,才知道要设置一下环境变量。然后才可以运行。(/etc/profile或~/.bashrc)
1 export LIBDIR=/usr/local/lib 2 export LD_LIBRARY_PATH=/usr/local/lib 3 export LD_RUN_PATH=/usr/local/lib
用gcc -E选项编译后的源代码
1 ev_io stdin_watcher; 2 ev_timer timeout_watcher; 3 4 5 6 7 static void stdin_cb(struct ev_loop *loop, ev_io *w,int revents) 8 { 9 puts("stdin ready"); 10 11 12 ev_io_stop(loop, w); 13 14 ev_break(loop, EVBREAK_ALL); 15 } 16 17 18 static void timeout_cb(struct ev_loop *loop, ev_timer *w,int revents) 19 { 20 puts("timeout"); 21 22 ev_break(loop, EVBREAK_ONE); 23 } 24 25 int main(int argc,char **args) 26 { 27 28 struct ev_loop *loop = ev_default_loop (0); 29 30 31 do { do { ((ev_watcher *)(void *)((&stdin_watcher)))->active = ((ev_watcher *)(void *)((&stdin_watcher)))->pending = 0; ( (ev_watcher *)(void *)(((&stdin_watcher))))->priority = (0); (((&stdin_watcher)))->cb = ((stdin_cb)); } while (0); do { ((&stdin_watcher))->fd = ((0)); ((&stdin_watcher))->events = ((EV_READ)) | EV__IOFDSET; } while (0); } while (0); 32 ev_io_start(loop,&stdin_watcher); 33 34 35 do { do { ((ev_watcher *)(void *)((&timeout_watcher)))->active = ((ev_watcher *)(void *)((&timeout_watcher)))->pending = 0; ( (ev_watcher *)(void *)(((&timeout_watcher))))->priority = (0); (((&timeout_watcher)))->cb = ((timeout_cb)); } while (0); do { ((ev_watcher_time *)((&timeout_watcher)))->at = ((5.5)); ((&timeout_watcher))->repeat = ((0)); } while (0); } while (0); 36 ev_timer_start(loop,&timeout_watcher); 37 38 39 ev_run(loop,0); 40 41 42 return 0; 43 }
1 do { 2 do { 3 ((ev_watcher *)(void *)((&stdin_watcher)))->active = ((ev_watcher *)(void *)((&stdin_watcher)))->pending = 0; 4 ( (ev_watcher *)(void *)(((&stdin_watcher))))->priority = (0); 5 (((&stdin_watcher)))->cb = ((stdin_cb)); 6 } while (0); 7 do { 8 ((&stdin_watcher))->fd = ((0)); 9 ((&stdin_watcher))->events = ((EV_READ)) | EV__IOFDSET; 10 } while (0); 11 } while (0); 12 ev_io_start(loop,&stdin_watcher);
Libev通过一个struct ev_loop结构表示一个事件驱动的框架。在这个框架里面通过ev_xxx结构,ev_init、ev_xxx_set、ev_xxx_start接口箱这个事件驱动的框架里面注册事件监控器,当相应的事件监控器的事件出现时,便会触发该事件监控器的处理逻辑,去处理该事件。处理完之后,这些监控器进入到下一轮的监控中。符合一个标准的事件驱动状态的模型。
Libev 除了提供了基本的三大类事件(IO事件、定时器事件、信号事件)外还提供了周期事件、子进程事件、文件状态改变事件等多个事件,这里我们用三大基本事件写一个例子。
1 #include <stdio.h> 2 #include <signal.h> 3 #include <string.h> 4 #include <sys/unistd.h> 5 #include <ev.h> 6 7 8 void io_action(struct ev_loop *main_loop,ev_io *io_w,int e) 9 { 10 int rst; 11 char buf[1024]; 12 memset(buf,0,sizeof(buf)); 13 puts("In IO action"); 14 read(STDIN_FILENO,buf,sizeof(buf)); 15 buf[1023]='