源码下载地址: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. Jemter+Badboy实战经验一(Badboy录制及基础功能)

    1. 使用工具: Apache Jemeter:http://jmeter.apache.org/download_jmeter.cgi (免费官网下载地址) BadBoy:   http://www ...

  2. javascript中parseint和number的区别

    本来是不想写这个的,网上也有,问题是讲得很不清楚,或者说我阅读能力差吧. 首先,解释一下定义的区别: parseInt将字符串(String)类型转为整数类型.Number() 函数把对象(Objec ...

  3. ReactJS React+Redux+Router+antDesign通用高效率开发模板,夜间模式为例

    工作比较忙,一直没有时间总结下最近学习的一些东西,为了方便前端开发,我使用React+Redux+Router+antDesign总结了一个通用的模板,这个技术栈在前端开发者中是非常常见的. 总的来说 ...

  4. otool是mac自带的工具

    找了一晚上otool的安装包,到最后才发现mac自带otool

  5. javascript-引用类型--Object类型

    引用类型是一种数据结构,本质是数据和功能的集合.引用类型有时也被称为对象定义,因为它们描述的是一类对象所具有的属性和方法.引用类型相当于java里面的类,javascript虽然是一门面向对象语言,但 ...

  6. 通过Eclipse3.1以上启动Tomcat访问不到tomcat管理界面的问题(转载)

    通过Eclipse插件启动Tomcat的问题 默认分类   2009-10-23 15:54   阅读118   评论0   字号: 大  中  小 目前在通过Eclipse中插件启动Tomcat时遇 ...

  7. SOA面向服务的架构理解

    Ø  单一应用架构 ·当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本. Ø  垂直应用架构 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几 ...

  8. IOS百度地图之--->第一篇《环境配置与基本使用》

    Ios 百度地图SDK简易使用说明:http://developer.baidu.com/map/index.php?title=iossdk 先道歉:对于原来上传的Demo我很抱歉,什么都没有,也没 ...

  9. js面向对象-原型链

    var Person = function (name) { this.name = name; } Person.prototype.say = function () { console.log( ...

  10. GitHub 添加 SSH keys

    首先在本地创建 SSH Keys $ ssh-keygen -t rsa -C "18817801185@163.com" 后面的邮箱即为 github 注册邮箱,之后会要求确认路 ...