#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. java 执行 class

    run.sh: #!/bin/bash CLASSPATH=. for jar in *.jar; do CLASSPATH=$CLASSPATH:$jardone CACHE_FILE=`pwd`/ ...

  2. Highcharts创建一个简单的柱状图

    新建一个html文件,将highcharts引入到你的页面后,通过两个步骤我们就可以创建一个简单的图表了. 1.创建div容器 在页面的 body部分创建一个div,并指定div 的 id,高度和宽度 ...

  3. 【hdoj_2082】找单词

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2082 此题采用母函数的知识求解,套用母函数模板即可: http://blog.csdn.NET/ten_s ...

  4. 【hdoj_2079】选课时间(母函数)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2079 此题采用母函数的知识求解,套用母函数模板即可: http://blog.csdn.net/ten_s ...

  5. WebDriver自动化测试工具(1)---环境搭建

    Webdriver是一个前端自动化测试工具,可以模拟用户点击链接,填写表单,点击按钮等操作,下面介绍其使用 一.下载WebdriverC#类库以及对应浏览器驱动 http://www.selenium ...

  6. windows10 易升 下载失败 解决方法

    在你剩余最大空间的硬盘里有一个名字大概是Windows10Updata的文件夹里找到一个名字14339开头的升级镜像,把这个文件的名字用记事本保存下来方便以后使用,同时在这个文件夹里还有一个叫prod ...

  7. 前端的3D(css3版本)--淘宝造物节3D创景的制作

    其实是依托Css3的功劳,先上一个例子 链接: https://pan.baidu.com/s/1cZ-mMI01FHO3u793ZhvF2w 提取码: d3s7代码地址:链接: https://pa ...

  8. file '/grub/i386-pc/normal.mod' not found.解决方案

    前言: 因为之前装的Ubuntu出了点问题,本想直接清除Ubuntu数据重新装一下,结果蹦出这么个BUG来,揪心,弄了大半天终于弄好了. 废话不多说,直接按教程走吧. GRUB启动: 在grub启动界 ...

  9. cookies和session区别

    session原理:1.session是保存在服务器端,理论上是没有是没有限制,只要你的内存够大   2.浏览器第一次访问服务器时会创建一个session对象并返回一个JSESSIONID=ID的值, ...

  10. 洛谷——P2097 资料分发1

    P2097 资料分发1 题目描述 有一些电脑,一部分电脑有双向数据线连接.如果一个电脑得到数据,它可以传送到的电脑都可以得到数据.现在,你有这个数据,问你至少将其输入几台电脑,才能使所有电脑得到数据. ...