源码下载地址:http://dist.schmorp.de/libev/

libev是一个高性能的事件循环库,比libevent库的性能要好。

安装:

 tar -zxf libev-4.15.tar.gz
cd libev-4.15
./configure
make
make install

设置环境变量:

设置一下环境变量(在文件/etc/profile中添加)。然后才可以运行。

 export LIBDIR=/usr/local/lib
export LD_LIBRARY_PATH=/usr/local/lib
export LD_RUN_PATH=/usr/local/lib 添加完成后运行:source /etc/profile 使设置生效;

没有接触过libev的新手一般对概念也是比较蒙的,我也不多做介绍,教你如何快速上手

对比说明吧!

示例一:不使用libev

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#define DAEMON_PORT 8888
#define MAX_LISTEN 1024 char get_manager_ip[]; int adminserver();
void pthread_adminserver(int client_sd); int main(int argc, char** argv){
strcpy(get_manager_ip, argv[]);
adminserver();
}
int adminserver()
{
int ret = ;
int i = ;
int max = ;
int nCurrentSocket = ;
FILE *fp;
int res;
int client_sd;
int server_sd;
int reuse_addr;
pthread_t p_tcpserver;
int client_addr_size ; struct sockaddr_in client_addr;
struct sockaddr_in server_addr;
char line[];
char listen_ip[];
char cmd_ip[]; char *pt;
char *edit; sprintf(cmd_ip,"ifconfig %s |grep 'addr:' >/get_manager_ip",get_manager_ip);
system(cmd_ip); fp = fopen("/get_manager_ip","rb");
if (fp == NULL)
{
printf("Cann't open get_manger_ip file!\n");
exit(-);
} memset(line,,);
fgets(line,,fp);
fclose(fp); pt=strstr(line, "addr:");
if (pt != NULL)
{
pt+=;
edit=strtok(pt," ");
strcpy(listen_ip,edit);
} server_sd=socket( AF_INET, SOCK_STREAM, ); if (server_sd < )
{
printf("ERROR: Cann't create socket!!!\n");
exit(-);
} bzero(&server_addr, sizeof(struct sockaddr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr=inet_addr(listen_ip);
server_addr.sin_port = htons(DAEMON_PORT); reuse_addr = ;
if (setsockopt (server_sd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)) < )
{
printf("setsockopt error\n");
close(server_sd);
return -;
} res = bind(server_sd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (res < )
{
printf("Cann't bind!res = %d,erro:%d, reason:%s.\n",res, errno, strerror(errno));
close(server_sd);
exit(-);
} if (listen( server_sd, MAX_LISTEN ) != ) {
printf("Cann't listen!\n");
close(server_sd);
exit(-);
} while()
{ client_addr_size = sizeof(client_addr);
client_sd = accept( server_sd, (struct sockaddr *)&client_addr, (socklen_t *)&client_addr_size);
if (pthread_create(&p_tcpserver, NULL, (void *)&pthread_adminserver, client_sd)!=)
{
printf("Could not create thread check_work_time\n");
return ;
}
}
close(server_sd);
exit();
} void pthread_adminserver(int client_sd)
{
int sockfd = ;
int rc;
char buffer[];
while()
{ //线程处理某个客户端的连接
memset(buffer,,);
rc=read(client_sd,buffer,);
if(strlen(buffer) == ){
close(client_sd); //关闭线程处理的客户端连接
pthread_exit();//终止该线程
}
printf("read date:\"%s\"\n",buffer); }
close(client_sd); //关闭线程处理的客户端连接
pthread_exit();//终止该线程
}

说明:这是一个处理多并发的socket服务端,通过while接收多条连接,然后通过线程去处理每条连接,简单易懂,但是 使用两个while(1),是一件很浪费系统资源是事情;

示例二:通过示例一改动,添加libev

先对比两个示例先用起来吧,欢迎大神指导。

 #include <ev.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h> #define PORT 8080
#define BUFFER_SIZE 1024
#define MAX_CONNECTIONS 10 struct ev_io *libevlist[MAX_CONNECTIONS] = {NULL}; void socket_accept_callback(struct ev_loop *loop, struct ev_io *watcher, int revents);
void socket_read_callback(struct ev_loop *loop, struct ev_io *watcher, int revents);
/*
Server Client socket socket
| |
v v
bind connect
| |
v v
listen write
| |
v v
accept read
| |
v v
read close
|
v
write
|
v
close
*/ int main() {
struct ev_loop *loop = ev_default_loop(); /* socket start */
int sd;
struct sockaddr_in addr;
int addr_len = sizeof(addr); struct ev_io *socket_watcher = (struct ev_io*)malloc(sizeof(struct ev_io));
struct ev_timer *timeout_watcher = (struct ev_timer*)malloc(sizeof(struct ev_timer)); // socket
sd = socket(PF_INET, SOCK_STREAM, );
if (sd < ) {
printf("socket error\n");
return -;
}
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY; // bind
if (bind(sd, (struct sockaddr*) &addr, sizeof(addr)) != ) {
printf("bind error\n");
return -;
}
// listen
if (listen(sd, SOMAXCONN) < ) {
printf("listen error\n");
return -;
}
// set sd reuseful
int bReuseaddr = ;
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (const char*) &bReuseaddr, sizeof(bReuseaddr)) != ) {
printf("setsockopt error in reuseaddr[%d]\n", sd);
return -;
}
/* socket end */ ev_io_init(socket_watcher, socket_accept_callback, sd, EV_READ);
ev_io_start(loop, socket_watcher); // while(1) {
ev_run(loop, );
// } return ;
} void socket_accept_callback(struct ev_loop *loop, struct ev_io *watcher, int revents) {
printf("I am: %d\n", getpid()); struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_sd; if (EV_ERROR & revents) {
printf("error event in accept\n");
return;
} // socket accept: get file description
client_sd = accept(watcher->fd, (struct sockaddr*) &client_addr, &client_len);
if (client_sd < ) {
printf("accept error\n");
return;
}
// too much connections
if (client_sd > MAX_CONNECTIONS) {
printf("fd too large[%d]\n", client_sd);
close(client_sd);
return;
} if (libevlist[client_sd] != NULL) {
printf("client_sd not NULL fd is [%d]\n", client_sd);
return;
} printf("client connected\n");
// ev_io watcher for client
struct ev_io *client_watcher = (struct ev_io*) malloc(sizeof(struct ev_io));
if (client_watcher == NULL) {
printf("malloc error in accept_cb\n");
return;
}
// listen new client
ev_io_init(client_watcher, socket_read_callback, client_sd, EV_READ);
ev_io_start(loop, client_watcher); libevlist[client_sd] = client_watcher;
} void socket_read_callback(struct ev_loop *loop, struct ev_io *watcher, int revents) {
char buffer[BUFFER_SIZE];
ssize_t read; if (EV_ERROR & revents) {
printf("error event in read\n");
return;
}
// socket recv
read = recv(watcher->fd, buffer, BUFFER_SIZE, ); // read stream to buffer
if (read < ) {
printf("read error\n");
return;
} if (read == ) {
printf("client disconnected.\n"); if (libevlist[watcher->fd] == NULL) {
printf("the fd already freed[%d]\n", watcher->fd);
}
else {
printf("fd:%d will be closed!\n",watcher->fd);
close(watcher->fd);
ev_io_stop(loop, libevlist[watcher->fd]);
free(libevlist[watcher->fd]);
libevlist[watcher->fd] = NULL;
}
return;
}
else {
printf("receive message[%d]says:%s\n",watcher->fd, buffer);
if(memcmp(buffer,"quit",strlen("quit")) == )
{
printf("recv quit cmd,fd:%d will be closed!\n",watcher->fd);
close(watcher->fd);
ev_io_stop(loop, libevlist[watcher->fd]);
free(libevlist[watcher->fd]);
libevlist[watcher->fd] = NULL;
return ;
}
} // socket send to client
send(watcher->fd, buffer, read, );
bzero(buffer, sizeof(buffer));
}

libev事件库使用笔记的更多相关文章

  1. libev事件库学习笔记

    一.libev库的安装 因为个人的学习环境是在ubuntu 12.04上进行的,所以本节仅介绍该OS下的安装步骤. 使用系统工具自动化安装: sudo apt-get install libev-de ...

  2. muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制

    目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ...

  3. muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor

    目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...

  4. muduo网络库学习笔记(三)TimerQueue定时器队列

    目录 muduo网络库学习笔记(三)TimerQueue定时器队列 Linux中的时间函数 timerfd简单使用介绍 timerfd示例 muduo中对timerfd的封装 TimerQueue的结 ...

  5. 利用epoll写一个"迷你"的网络事件库

    epoll是linux下高性能的IO复用技术,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率.另一点原因就是获取 ...

  6. ktouch移动端事件库

    最近闲来无事,写了个移动端的事件库,代码贴在下面,大家勿拍. /** @version 1.0.0 @author gangli @deprecated 移动端触摸事件库 */ (function ( ...

  7. Yarn的服务库和事件库使用方法

    事件类型定义: package org.apache.hadoop.event; public enum JobEventType { JOB_KILL, JOB_INIT, JOB_START } ...

  8. Threejs 的场景查看 - 几个交互事件库助你方便查看场景

    Threejs 的场景查看 - 几个交互事件库助你方便查看场景 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&q ...

  9. python 库安装笔记

    python 库安装笔记 zoerywzhou@163.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2017-2-22 友情提示 安装python库的过程中 ...

随机推荐

  1. js小动画算法

    function step(A,B,rate,callback){ A = A + (B - A) / (rate || 2); if(Math.abs(A-B) < 1){ callback( ...

  2. Objective-C日记-之类别Category

    类别Category 1,概述 为现有类添加新的方法,这些新方法的Objective-C的术语为“类别”. 2,用法 a,声明类别 @interface NSString(NumberConvenie ...

  3. 九度oj1163题

    题目描述: 输入一个整数n(2<=n<=10000),要求输出所有从1到这个整数之间(不包括1和这个整数)个位为1的素数,如果没有则输出-1. 输入: 输入有多组数据. 每组一行,输入n. ...

  4. WebX框架学习笔记之一

    Webx是什么? Webx是一套基于Java Servlet API的通用Web框架.它在Alibaba集团内部被广泛使用.从2010年底,向社会开放源码. Webx的发展历史 2001年,阿里巴巴内 ...

  5. JAVA基础知识(2)--关键字static的使用

    在Java类中声明属性.方法和内部类时,可使用关键字static作为修饰符,static标记的属性和方法可以由整个类进行共享,因此static修饰的属性称为类成员或者称为类方法:static修饰的方法 ...

  6. 【树莓派】iptables相关配置

    关于iptables的配置,参见官方资料:http://wiki.ubuntu.org.cn/IptablesHowTo 最好. 进入iptables # sudo iptables -L 列出目前的 ...

  7. Android设计模式之代理模式

    代理模式: 为其他对象提供一种代理以控制对这个对象的访问 Subject类定义了RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy inte ...

  8. iOS开发之UIPopoverController

    1.概述 是iPad开发中常见的一种控制器(在iPhone上不允许使用),跟其他控制器不一样的是,它直接继承自NSObject,并非继承自UIViewController,它只占用部分屏幕空间来呈现信 ...

  9. CSS常见兼容性问题总结

    原文链接:渔人码头 http://www.cnblogs.com/imwtr/p/4340010.html?utm_source=tuicool&utm_medium=referral 浏览器 ...

  10. Yahoo前端优化十四条军规

    相信互联网已经越来越成为人们生活中不可或缺的一部分.Ajax,flex等等富客户端的应用使得人们越加“幸福”地体验着许多原先只能在C/S实 现的功能. 比如Google机会已经把最基本的office应 ...