#include <ev.h>
#include <stdio.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h> #define PORT 6666
#define BUFFER_SIZE 2048
#define MAX_ALLOWED_CLIENT 10240 struct ev_io *libevlist[MAX_ALLOWED_CLIENT] = {NULL}; void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents); void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents); void timer_beat(struct ev_loop *loop, struct ev_timer *watcher, int revents); int freelibev(struct ev_loop *loop, int fd); int main()
{
struct ev_loop *loop=ev_default_loop();
int sd;
struct sockaddr_in addr;
int addr_len = sizeof(addr); //创建一个io watcher和一个timer watcher
struct ev_io socket_accept;
struct ev_timer timeout_w;
//创建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 -;
}
//设置fd可重用
int bReuseaddr=;
if(setsockopt(sd,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(bReuseaddr)) != )
{
printf("setsockopt error in reuseaddr[%d]\n", sd);
return ;
} //初始化io watcher,用于监听fd
ev_io_init(&socket_accept, read_cb, sd, EV_READ);
ev_io_start(loop, &socket_accept); ev_run(loop, ); return ;
} void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{ // 如果有链接,则继续监听fd; struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_sd;
//创建客户端的io watcher
struct ev_io *w_client = (struct ev_io*) malloc(sizeof(struct ev_io)); if(w_client == NULL)
{
printf("malloc error in accept_cb\n");
return ;
} if(EV_ERROR & revents)
{
printf("error event in accept\n");
return ;
} //获取与客户端相连的fd
client_sd = accept(watcher->fd, (struct sockaddr*)&client_addr, &client_len);
if(client_sd < )
{
printf("accept error\n");
return;
}
//如果连接数超出指定范围,则关闭连接
if( client_sd > MAX_ALLOWED_CLIENT)
{
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");
//监听新的fd
ev_io_init(w_client, read_cb, client_sd, EV_READ);
ev_io_start(loop, w_client); libevlist[client_sd] = w_client; } void read_cb(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 ;
}
//正常的recv
read = recv(watcher->fd, buffer, BUFFER_SIZE, );
if(read < )
{
printf("read error\n");
return;
} if(read == )
{
printf("client disconnected.\n");
//ev_io_stop(loop, watcher);
//free(watcher);
//如果客户端断开连接,释放响应的资源,并且关闭监听
freelibev(loop, watcher->fd);
return;
}
else
{
//buffer[read] = '\0';
printf("receive message:%s\n", buffer);
}
//返回给客户端
send(watcher->fd, buffer, read, );
bzero(buffer, read);
} int freelibev(struct ev_loop *loop, int fd)
{
//清理相关资源 if(libevlist[fd] == NULL)
{
printf("the fd already freed[%d]\n", fd);
return -;
} close(fd);
ev_io_stop(loop, libevlist[fd]);
free(libevlist[fd]);
libevlist[fd] = NULL;
return ;
}

libev客户端的更多相关文章

  1. [译]libev和libevent的设计差异

    本文译自what's the difference between libev and libevent? 作者是libev作者 [问]两个库都是为异步io调度而设计,在Linux上都是使用epoll ...

  2. 使用 libevent 和 libev 提高网络应用性能——I/O模型演进变化史

    构建现代的服务器应用程序需要以某种方法同时接收数百.数千甚至数万个事件,无论它们是内部请求还是网络连接,都要有效地处理它们的操作. 有许多解决方案,但事件驱动也被广泛应用到网络编程中.并大规模部署在高 ...

  3. 使用 libevent 和 libev 提高网络应用性能

    使用 libevent 和 libev 提高网络应用性能 Martin C. Brown, 作家, Freelance 简介: 构建现代的服务器应用程序需要以某种方法同时接收数百.数千甚至数万个事件, ...

  4. libev事件库使用笔记

    源码下载地址:http://dist.schmorp.de/libev/ libev是一个高性能的事件循环库,比libevent库的性能要好. 安装: tar -zxf libev-4.15.tar. ...

  5. ibevent 和 libev 提高网络应用性能【转】

    转自:https://www.cnblogs.com/kunhu/p/3632285.html 构建现代的服务器应用程序需要以某种方法同时接收数百.数千甚至数万个事件,无论它们是内部请求还是网络连接, ...

  6. libevent 和 libev 提高网络应用性能

    构建现代的服务器应用程序需要以某种方法同时接收数百.数千甚至数万个事件,无论它们是内部请求还是网络连接,都要有效地处理它们的操作.有许多解决方 案,但是 libevent 库和 libev 库能够大大 ...

  7. Redis学习之路(008)- Redis C语言客户端库hiredis文档翻译

    Hiredis是Redis数据库一个轻量的C语言客户端库. 之所以轻量是由于它只是简单的提供了对redis操作语句支持的接口,并没有实现具体的操作语句的功能.但正是由于这种设计使我们只要熟悉了通用的r ...

  8. (libev) cannot allocate xxx bytes, aborting 问题的一种触发条件

    最近在项目中使用了libev,遇到一个很奇怪的crash,服务器运行随机时间后有一定的概率奔溃,输出的最后一行log是: (libev) cannot allocate xxx bytes, abor ...

  9. ss-libev 源码解析local篇(1): ss_local的启动,客户端连入

    学习研究ss-libev的一点记录(基于版本3.0.6) ss_local主要代码在local.c中,如果作为一个库编译,可通过start_ss_local_server启动local server. ...

随机推荐

  1. python_day1学习笔记

    一.Python 2.7.x 和 3.x 版本的区别小结 print函数 1.python2 import platform print ‘Python’, platform.python_versi ...

  2. python基础(4)---解释器、编码、字符拼接

    1.Python种类 1.1Cpython Python官方版本,使用C语言实现,运行机制:先编译.py(源码文件)->pyc(字节码文件),最终执行时先将字节码转换成机器码,然后交给cpu执行 ...

  3. PHP7.3发布啦

    作为PHP5的最后一个版本,也是目前使用最广泛的PHP版本,PHP 5.6始于公元2014年(不是1804年,嘿嘿),其第一个测试版PHP 5.6 alpha 1版于2014年1月发布.随机产生了第一 ...

  4. jquery请求解析xml

    我们使用jque.ajax来做这个实验.其核心实现原理就是将请求回来的xml数据用$()选择器封装,然后进行傻瓜式操作. 代码如下: 需要注意的是请求数据格式要声明成:xml.不然不生效. $.aja ...

  5. Codeforces 1082 B. Vova and Trophies-有坑 (Educational Codeforces Round 55 (Rated for Div. 2))

    B. Vova and Trophies time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  6. zookeeper,hadoop安装部署其实与防火墙无关

    网上查看了很多人关于hadoop,zookeeper的文章,大多都把关闭防火墙作为首要前提,个人觉得这大可不必. 首先你需要知道你部署的是什么东西,它需要哪些端口即可.把相关端口打开就可以了啊.然后把 ...

  7. TYVJ2002 扑克牌

    卢克生日那天,汉来找卢克玩扑克牌,玩着玩着汉觉得太没意思了,于是决定给卢克一个考验汉把一副扑克牌(54张)随机洗匀,倒扣着放成一摞.然后卢克从上往下一次翻开每张牌,每翻开一张黑桃,红桃,梅花或方块,就 ...

  8. 洛谷—— P2562 [AHOI2002]Kitty猫基因编码

    P2562 [AHOI2002]Kitty猫基因编码 题目描述 小可可选修了基础生物基因学.教授告诉大家 Super Samuel 星球上 Kitty猫的基因的长度都是 2 的正整数次幂 ), 全是由 ...

  9. JZYZOJ1386 扑街 状压dp

    http://172.20.6.3/Problem_Show.asp?id=1386   有一个W行H列的街道,需要用1*2小砖铺盖,小砖之间互相不能重叠,问有多少种不同的铺法? 数组f的不往后延伸指 ...

  10. 全网第二好懂的FFT(快速傅里叶变换)

    声明:本FFT是针对OI的.专业人员请出门左拐. Ⅰ前言 很久以前,我打算学习FFT. 然而,算法导论讲的很详细,却看不懂.网上博客更别说了,什么频率之类的都来了.我暗自下了决心:写一篇人看得懂的FF ...