#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <ev.h> #define PORT 12100
#define BUFFER_SIZE 1024
#define MAX_LISTEN 5 /*初始化服务端*/
int server_socket_init(int *sd, char *ipaddr, uint16_t port)
{
//创建socket
int sock = socket(AF_INET, SOCK_STREAM, );
if (- == sock)
goto err1;
//设置立即释放端口并可以再次使用
int reuse = ;
if (- == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)))
goto err2;
//设置为非阻塞
if (- == fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK))
goto err2;
struct sockaddr_in addr;
memset(&addr, , sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (NULL == ipaddr) {
addr.sin_addr.s_addr = htonl(INADDR_ANY);
} else {
addr.sin_addr.s_addr = inet_addr(ipaddr);
}
//绑定监听
if (- == bind(sock, (struct sockaddr *)&addr, sizeof(addr)))
goto err2;
if (- == listen(sock, MAX_LISTEN))
goto err2;
*sd = sock;
return ;
err2:
close(sock);
err1:
return -;
} /*读回调*/
void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
char buffer[BUFFER_SIZE] = {};
if (EV_ERROR & revents) {
printf("read got invalid event...\r\n");
return;
}
int res = ;
int32_t bytes = read(watcher->fd, buffer, sizeof(buffer));
if (- == bytes) {
//tcp Error
if (EINTR != errno && EAGAIN != errno) {
res = ;
}
} else if ( == bytes) {
//tcp Close
res = ;
}
if ( != res) {
//关闭事件循环并释放watcher
printf("TCP CLOSE\r\n");
ev_io_stop(loop,watcher);
free(watcher);
} else {
printf("READ:\r\n %s\r\n", buffer);
}
} /*accept回调函数*/
void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
if (EV_ERROR & revents) {
printf("accept got invalid event...\r\n");
return;
}
//accept连接
int sock = accept(watcher->fd, (struct sockaddr *)&client_addr, &client_len);
if (- == sock) {
return;
}
//设置非阻塞
if(- == fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK)) {
close(sock);
return;
}
printf("Successfully connected with client: %s:%u\r\n", \
inet_ntoa(client_addr.sin_addr), client_addr.sin_port);
//加入事件循环
struct ev_io *w_client = (struct ev_io*) malloc (sizeof(struct ev_io));
ev_io_init(w_client, read_cb, sock, EV_READ);
ev_io_start(loop, w_client);
} int main()
{
int sd;
struct ev_io w_accept;
struct ev_loop *loop = ev_loop_new(EVBACKEND_EPOLL);
if (NULL == loop) {
printf("loop create failed\r\n");
return -;
}
if (server_socket_init(&sd, NULL, PORT) < ) {
printf("server init failed\r\n");
return -;
}
ev_io_init(&w_accept, accept_cb, sd, EV_READ);
ev_io_start(loop, &w_accept);
ev_run(loop, );
return ;
}
————————————————
版权声明:本文为CSDN博主「Dancer__Sky」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Dancer__Sky/article/details/85159058

libev+TCP服务器事件轮询实例demo的更多相关文章

  1. 【译】理解node.js事件轮询

    Node.js的第一个基本论点是I/O开销很大. 当前编程技术中等待I/O完成会浪费大量的时间.有几种方法可以处理这种性能上的影响: 同步:每次处理一个请求,依次处理.优点:简单:缺点:任何一个请求都 ...

  2. node.js事件轮询(1)

    事件轮询(引用) 事件轮询是node的核心内容.一个系统(或者说一个程序)中必须至少包含一个大的循环结构(我称之为"泵"),它是维持系统持续运行的前提.nodejs中一样包含这样的 ...

  3. Node.js的异步IO和事件轮询

     想象一下,以前我们在写程序时, 如果程序在I/O上阻塞了,当有更多请求过来时,服务器会怎么处理呢?在这种情景中通常会用多线程的方式.一种常见的实现是给每个连接分配一个线程,并为那些连接设置一个线程池 ...

  4. 12.nodejs事件轮询机制

    一:nodejs事件轮询机制  就是  函数的执行顺序 <script type="text/javascript"> setImmediate(function(){ ...

  5. JS高阶---事件循环模式(事件轮询)

    大纲: 相关知识点: 主体: (1)模型原理 JS部分:初始化代码执行 WebAPIS:执行上下文对象(不是一个真的对象,而是一个抽象的虚拟对象,可以看做栈里的一个区域,包含很多对象) setTime ...

  6. 浅析libuv源码-node事件轮询解析(2)

    上一篇讲了轮询的边角料,这篇进入正题.(竟然真有人看我博客,上两个图给你们整理下思路) 这是轮询总流程图. 下图为本节内容简图. Poll for I/O The loop blocks for I/ ...

  7. 浅析libuv源码-node事件轮询解析(1)

    好久没写东西了,过了一段咸鱼生活,无意中想起了脉脉上面一句话: 始终保持自己的竞争力.所以,继续开写! 一般的JavaScript源码看的已经没啥意思了,我也不会写什么xx入门新手教程,最终决定还是啃 ...

  8. 面试题: nodejs 的事件轮询机制

    setTimeout(function(){ console.log('setTimeout()执行了') },0) setImmediate(function(){ console.log('set ...

  9. nodejs事件轮询详述

    目录 概述 nodejs特点 事件轮询 关于异步方法 概述 关于nodejs的介绍网上资料非常多,最近由于在整理一些函数式编程的资料时,多次遇到nodejs有关的内容.所以就打算专门写一篇文章总结一下 ...

随机推荐

  1. DataNode 详解及HDFS 2.X新特性

    1. 工作机制 一个数据块在 DataNode 上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳. DataNode 启动后向 Name ...

  2. 《鸟哥的Linux私房菜:基础学习篇》读书笔记之第一部分

    一.如何学习Linux 1. Linux基础知识 (1) 计算机概论与硬件相关知识. (2) 先从Linux的安装与命令学起. (3) Linux操作系统的基础技能.如用户/用户组.权限.程序等概念. ...

  3. EXCEL 查找某个字符在字符串中最后一次出现的位置

    在EXCEL文档里想从很长的文件路径中取得文件名,[数据]→[分列]是个不错的选择,但用函数会显得更高大上一些. 首先,需要获取最后一个"\"所在的位置. 方法1: FIND(&q ...

  4. # 滚动Hash

    滚动Hash 假设字符串\(C=c_1*c_2*...c_m\),定义Hash函数\(H(C)=(C_1*b^{m-1}+C_2*b^{m-2}+...C_m*b^{0})mod\; h\) 从k开始 ...

  5. 从cbv到fbv:用函数写视图与用类写视图的区别(drf与restful)

    FBV 基于函数的视图 (function base views) CBV 基于类的视图 (class base views) 也就是说我们是用函数编写视图~还是类编写视图我们来看下两个的简单实现 u ...

  6. fiddler笔记:Composer选项卡

    1.Composer选项卡介绍 Composer选项卡功能是可以手动构建和发送HTTP.HTTPS和FTP请求. 支持将Web Session列表中选中的Session拖入Composer选项卡,然后 ...

  7. 20190724-Python网络数据采集/第 2 章 复杂HTML解析-导航树/正则表达式

    1. 导航树 经典的HTML树状结构 直接看下面的代码示例:(注意目标网页的标签大小写等细节,易出bug) from urllib.request import urlopen from bs4 im ...

  8. docker使用的一些需要注意事项

    1.程序需要前台运行 程序必须前台执行,如果是java进程的话  不要有nohup   或者使用service的方式进行后台运行 否则可能会出现频繁启动应用的问题 原因就是docker只能管理运行中的 ...

  9. Spring在Thread中注入Bean无效的解决方式

    在Spring项目中,有时需要新开线程完成一些复杂任务,而线程中可能需要注入一些服务.而通过Spring注入来管理和使用服务是较为合理的方式.但是若直接在Thread子类中通过注解方式注入Bean是无 ...

  10. Docker本地镜像发布到阿里云和从阿里云拉取镜像

    登录阿里云官网,找到容器镜像服务 进入镜像仓库,创建仓库 输入信息 选择本地仓库 这里我要将这个镜像提交到仓库 回到仓库列表,点击管理 docker login --username=cn丶moti ...