#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. LeetCode解题报告—— Bus Routes

    We have a list of bus routes. Each routes[i] is a bus route that the i-th bus repeats forever. For e ...

  2. Python基础系列----函数,面向对象,异常

    1.前言                                                                                               前 ...

  3. 五十九 数据库访问 使用MySQL

    MySQL是Web世界中使用最广泛的数据库服务器.SQLite的特点是轻量级.可嵌入,但不能承受高并发访问,适合桌面和移动应用.而MySQL是为服务器端设计的数据库,能承受高并发访问,同时占用的内存也 ...

  4. 【剑指offer】面试题 55. 二叉树的深度

    面试题 55. 二叉树的深度 题目一:二叉树的深度 题目描述:输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. Java 实现 ...

  5. QTextCodec中的setCodecForTr等终于消失了 (Qt5)

    原文请看:http://www.cnblogs.com/lexus/archive/2012/05/01/2478150.html QT牛博 QTextCodec中的setCodecForTr等终于消 ...

  6. Linux操作命令(六)

    本次实验将介绍 Linux 命令中 wc 和 grep 命令的用法. wc grep 1.wc wc命令是一个统计的工具,主要用来显示文件所包含的行.字和字节数. wc命令是word count的缩写 ...

  7. 简单了解gzip、bzip2、xz

    压缩工具gzip.bzip2.xz分别对应压缩格式.gz..bz2..xz.不过tar命令已经可以满足大部分使用,所以这些格式只简单了解一下.gzip压缩速度最快,xz压缩率最高,bz2适中.一般这三 ...

  8. 【java回调】同步/异步回调机制的原理和使用方法

    回调(callback)在我们做工程过程中经常会使用到,今天想整理一下回调的原理和使用方法. 回调的原理可以简单理解为:A发送消息给B,B处理完后告诉A处理结果.再简单点就是A调用B,B调用A. 那么 ...

  9. 【动态规划/二维背包问题】mr355-三角形牧场

    应该也是USACO的题目?同样没有找到具体出处. [题目大意] 和所有人一样,奶牛喜欢变化.它们正在设想新造型牧场.奶牛建筑师Hei想建造围有漂亮白色栅栏的三角形牧场.她拥有N(3≤N≤40)块木板, ...

  10. Codeforces Beta Round #3 C. Tic-tac-toe 模拟题

    C. Tic-tac-toe 题目连接: http://www.codeforces.com/contest/3/problem/C Description Certainly, everyone i ...