源码下载地址: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. appium初学者,使用之检查appium环境报错Could not detect Mac OS X Version from sw_vers output: '10.12.1’,

    这个问题存在的原因就是appium不兼容最新的mac10.12版本. 由于10.12是最新mac版本,appium1.5.3并未提供支持,所以: 在终端输入grep -rl "Could n ...

  2. Web平台安装及检测程序

    软件名称:microsoft web platform installer 上图: 可以看做是一个App Store, 你再也不用东奔西跑去找什么开发软件,CMS等等了,直接打开这个,勾选上就安装吧, ...

  3. ASP日期格式化函数

    Public Function GetFormatDate(DateAndTime, para)On Error Resume NextDim y, m, d, h, mi, s, strDateTi ...

  4. 1644: [Usaco2007 Oct]Obstacle Course 障碍训练课

    1644: [Usaco2007 Oct]Obstacle Course 障碍训练课 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 383  Solved ...

  5. python + selenium <二>

    应用Webdriver,实现自动化 #coding:gbk from selenium import webdriver import os from selenium.webdriver.suppo ...

  6. Python模块发布

    项目根目录添加setup.py模块: from distutils.core import setup setup( name="模块名字", version="1.0. ...

  7. Hibernate写配置文件无提示信息解决

    把Hibernate的相关jar包引入工程后,在配置hibernate.cfg.xml时没有提示信息,对于开发人员来说,那么多标签,标签有那么多属性,全部都记住显然是不可能的,遇到这种情况是很头疼的事 ...

  8. Chrome 下动画卡顿问题的另一种可能

    [现象] 动画出现了明显的卡顿,且仅仅出现在 chrome 中. [原因排查] 一开始使用了css动画的时候已经出现了卡顿.找到如下的文章:CSS3 动画卡顿解决方案.深入浏览器理解CSS anima ...

  9. JVM中GC浅解:垃圾回收的了解

    1.为什么要有GC 没有GC的世界,我们需要手动进行内存管理,但是内存管理是纯技术活,又容易出错.但是我们写码的目的是为了解决业务问题,所以可以把这种纯技术活自动化,当然自动化也是有代价的. 2.垃圾 ...

  10. 一文让你从此告别HTTP乱码(一)Request篇

    #circle { background-color: #8fcbec; border: 3px } 概述 开发Web项目的过程中,经常遇到浏览器中显示的内容乱码,或者服务器获取浏览器请求参数时乱码的 ...