libev事件库使用笔记
源码下载地址: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事件库使用笔记的更多相关文章
- libev事件库学习笔记
一.libev库的安装 因为个人的学习环境是在ubuntu 12.04上进行的,所以本节仅介绍该OS下的安装步骤. 使用系统工具自动化安装: sudo apt-get install libev-de ...
- muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制
目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ...
- muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor
目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...
- muduo网络库学习笔记(三)TimerQueue定时器队列
目录 muduo网络库学习笔记(三)TimerQueue定时器队列 Linux中的时间函数 timerfd简单使用介绍 timerfd示例 muduo中对timerfd的封装 TimerQueue的结 ...
- 利用epoll写一个"迷你"的网络事件库
epoll是linux下高性能的IO复用技术,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率.另一点原因就是获取 ...
- ktouch移动端事件库
最近闲来无事,写了个移动端的事件库,代码贴在下面,大家勿拍. /** @version 1.0.0 @author gangli @deprecated 移动端触摸事件库 */ (function ( ...
- Yarn的服务库和事件库使用方法
事件类型定义: package org.apache.hadoop.event; public enum JobEventType { JOB_KILL, JOB_INIT, JOB_START } ...
- Threejs 的场景查看 - 几个交互事件库助你方便查看场景
Threejs 的场景查看 - 几个交互事件库助你方便查看场景 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&q ...
- python 库安装笔记
python 库安装笔记 zoerywzhou@163.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2017-2-22 友情提示 安装python库的过程中 ...
随机推荐
- CentOs下安装PHP环境的步骤
前言 在CentOs环境下安装php开发环境,需要首先安装一些源文件,然后使用yum命令直接安装即可,在Fedora 20 源中已经有了PHP的源,直接可以使用以下命令安装即可: # yum inst ...
- ArrayList源码剖析
ArrayList简介 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下,多线 ...
- 3631: [JLOI2014]松鼠的新家
3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 707 Solved: 342[Submit][Statu ...
- Java集合ArrayList源码解读
最近在回顾数据结构,想到JDK这样好的代码资源不利用有点可惜,这是第一篇,花了心思.篇幅有点长,希望想看的朋友认真看下去,提出宝贵的意见. :) 内部原理 ArrayList 的3个字段 priva ...
- Java synchronized 关键字的实现原理
数据同步需要依赖锁,那锁的同步又依赖谁?synchronized给出的答案是在软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的CPU指令,大家可能会进一步追问:JVM底层又是如何实现sy ...
- 009 Java集合浅析4
前面一篇教程中,我们分析了List派别中的最常见也最重要的一个类ArrayList<E>.从我们的分析来看,ArrayList作为动态数组的模拟,使用的是连续内存空间来存储数据,带来了可随 ...
- freemodbus移植讲解 ZZ
一 为什么要移植Freemodbus 为什么要移植Freemodbus,这个问题需要从两个方面来回答.第一,modbus是一个非常好的应用层协议,它很简洁也相对完善.对于还没有接触过modbus的 ...
- CCF 201609-4 交通规划
问题描述 试题编号: 201609-4 试题名称: 交通规划 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 G国国王来中国参观后,被中国的高速铁路深深的震撼,决定为自己的国家 ...
- 启动tomcat直接报错:org.apache.tomcat.util.digester.Digester startElement
今天很奇怪,自己手动搭建了一个ssm(spring+springmvc+mybatis)的项目,然后添加到tomcat下,启动直接报错: 2017-3-19 9:24:47 org.apache.to ...
- .net Core 1.0.1 下的Web框架的的搭建过程step by step
环境:ubuntu+VScode 数据库:mysql ,ORM框架:chloe 官网 看完本篇文章你能学会 在Vscode下创建项目,一些基础的命令 ,以及得到一个配置文件的简单读取实例 1,在VS ...