#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. numpy及scipy的使用

    numpy的使用 把list A转换为numpy 矩阵 np.array(A) np.array(A, 'int32') numpy加载txt文件里面的矩阵 matrix = np.loadtxt(t ...

  2. MVC - 12.HtmlHelper

    1.动态生成URL @Url.Action("Index3","Stu3") @Url.RouteUrl("Default2", new { ...

  3. StyleCop setting

    StyleCop下载地址:http://stylecop.codeplex.com/ -Documentation Rules 文档化注释规则 -Element Documentaion 变量的文档化 ...

  4. [lampp] 不能通过互联网连接数据库 MySQL is not accessable via network

    LAMPP安装目录下的/etc/my.cnf文件注释掉skip-networking #skip-networking#skip-networking

  5. 并发系列3-大白话聊聊Java并发面试问题之谈谈你对AQS的理解?【石杉的架构笔记】

  6. 利用FusionCharts制作统计报表

    今天在开发中需要用到统计报表,于是就查找了一下FusionCharts的用法,下面来总结一下利用FusionCharts怎么制作统计报表 1.建表 首先要建立所要统计报表的表,表的字段越多,统计的维度 ...

  7. BZOJ 4027:[HEOI2015]兔子与樱花(贪心+树形DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4027 [题目大意] 樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1 ...

  8. [Contest20170910]string

    给定一个由且仅由字符$'H','T'$构成的字符串$S$ 给定一个最初为空的字符串$T$,每次随机地在$T$的末尾添加$'H'$或者$'T'$ 问当$S$为$T$的后缀时,在末尾添加字符的期望次数 妙 ...

  9. 【枚举】【最小表示法】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game

    给你一个n*m的字符矩阵,将横向(或纵向)全部裂开,然后以任意顺序首尾相接,然后再从中间任意位置切开,问你能构成的字典序最大的字符串. 以横向切开为例,纵向类似. 将所有横排从大到小排序,枚举最后切开 ...

  10. 随机数选择器 Exercise07_13

    import java.util.Scanner; /** * @author 冰樱梦 *时间:2018年下半年 *题目:随机数选择器 */ public class Exercise07_13 { ...