回想起之前自己用纯c手动写epoll循环,libevent用起来还真是很快捷啊!重写了之前学习的时候的一个例子,分别用纯c与libevent来实现。嗯,为了方便对比一下,就一个文件写到黑了。

纯c版:

一个server.c与client.c共同引用的头文件func.h

 #include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<dirent.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>
#include<stdlib.h>
#include<sys/time.h>
#include<sys/select.h>
#include<sys/mman.h>
#include<sys/wait.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<signal.h>
#include<pthread.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/epoll.h>
#include<fcntl.h>

client.c

  ///
/// @file client.c
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-10-19 22:21:01
/// #include "func.h" int socket_init(char * pst_ip, short short_port);
int epoll_init(int int_sfd);
int epoll_add(int int_sfd, int int_epfd);
int epoll_del(int int_sfd, int int_epfd);
int epoll_loop(int int_sfd, int int_epfd);
int on_send_message_callback(int int_sfd, int int_epfd);
int on_recv_message_callback(int int_fd, int int_epfd); int main(int argc, char* argv[])
{
if(argc != )
{
printf("%s ip port\n",argv[]);
return -;
} char * pst_ip = argv[];
short short_port = atoi(argv[]); //初始化socket
int int_sfd = socket_init(pst_ip, short_port);
if (- == int_sfd)
{
printf("socket init fail...\n");
return -;
} //初始化epoll
int int_epfd = epoll_init(int_sfd); //epoll循环
epoll_loop(int_sfd, int_epfd);
return ;
} int socket_init(char * pst_ip, short short_port)
{
//初始化socket
int int_sfd = socket(AF_INET,SOCK_STREAM,);
if(- == int_sfd)
{
perror("socket");
return -;
}
int int_ret; //连接服务器
struct sockaddr_in sock_client;
sock_client.sin_family = AF_INET;
sock_client.sin_addr.s_addr = inet_addr(pst_ip);
sock_client.sin_port = htons(short_port); printf("prepare to connect ip:%s port:%d\n", pst_ip, short_port);
int_ret = connect(int_sfd, (struct sockaddr*)&sock_client, sizeof(sock_client));
if(- == int_ret)
{
perror("connect");
return -;
}
printf("connect ip:%s port:%d success!\n", pst_ip, short_port); //修改文件描述符状态为非阻塞
int status;
status=fcntl(int_sfd,F_GETFL);
status=status|O_NONBLOCK;
fcntl(int_sfd,F_SETFL,status); return int_sfd;
} int epoll_add(int int_fd, int int_epfd)
{
struct epoll_event epoll_ev;
epoll_ev.events = EPOLLIN|EPOLLET;
epoll_ev.data.fd = int_fd;
epoll_ctl(int_epfd, EPOLL_CTL_ADD, int_fd, &epoll_ev);
return ;
} int epoll_del(int int_fd, int int_epfd)
{
struct epoll_event epoll_ev;
epoll_ev.events = EPOLLIN|EPOLLET;
epoll_ev.data.fd = int_fd;
epoll_ctl(int_epfd, EPOLL_CTL_DEL, int_fd, &epoll_ev);
return ;
} int epoll_init(int int_sfd)
{
int int_epfd;
int_epfd = epoll_create();
epoll_add(, int_epfd);
epoll_add(int_sfd, int_epfd);
return int_epfd; } int on_send_message_callback(int int_sfd, int int_epfd)
{
char pst_buffer[];
int int_ret;
memset(pst_buffer, , sizeof(pst_buffer));
int_ret = read(, pst_buffer, sizeof(pst_buffer) - );
printf("input = %s; ret = %d\n", pst_buffer, int_ret);
if( == int_ret)
{
printf("bye~\n");
epoll_del(int_sfd, int_epfd);
epoll_del(, int_epfd);
return -;
} else
{
printf("send = %s\n", pst_buffer);
int_ret = send(int_sfd, (void*)pst_buffer, sizeof(pst_buffer) - , );
if(- == int_ret)
{
perror("send");
epoll_del(int_sfd, int_epfd);
epoll_del(, int_epfd);
return -;
}
printf("send success!\n");
}
return int_ret;
} int on_recv_message_callback(int int_fd, int int_epfd)
{
char pst_buffer[];
int int_ret;
while()
{
memset(pst_buffer, , sizeof(pst_buffer));
int_ret = recv(int_fd, (void*)pst_buffer, sizeof(pst_buffer) - , );
if( > int_ret)
{
break;
}
if( == int_ret)
{
printf("The server has been offline\n");
epoll_del(int_fd, int_epfd);
return -;
}
printf("%s", pst_buffer);
}
printf("\n"); return ;
} int epoll_loop(int int_sfd, int int_epfd)
{
struct epoll_event epoll_evs[];
int int_ret;
int int_event_num;
int int_idx;
int is_loop = ; //循环体
while(is_loop)
{
memset(epoll_evs, , sizeof(epoll_evs)); //等待事件
int_event_num = epoll_wait(int_epfd, epoll_evs, , -);
if (int_event_num > )
{
printf("someting in...\n");
for(int_idx = ; int_idx < int_event_num; ++int_idx)
{
if(epoll_evs[int_idx].events == EPOLLIN)
{
if(epoll_evs[int_idx].data.fd == )
{
//要发送消息
int_ret = on_send_message_callback(int_sfd, int_epfd);
if(- == int_ret)
{
printf("on send message callback fail...\n");
is_loop = ;
break;
} if( == int_ret)
{
is_loop = ;
break;
}
}
else if(epoll_evs[int_idx].data.fd == int_sfd)
{
//收到消息
int_ret = on_recv_message_callback(int_sfd, int_epfd);
if(- == int_ret)
{
printf("on recv message callback fail...\n");
is_loop = ;
break;
}
}
}
}
}
}
return ;
}

server.c

  ///
/// @file server.c
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-10-19 21:27:33
/// #include "func.h" int socket_init();
int epoll_init(int int_sfd);
int epoll_add(int int_sfd, int int_epfd);
int epoll_del(int int_sfd, int int_epfd);
int epoll_loop(int int_sfd, int int_epfd);
int on_accept_callback(int int_sfd, int int_epfd);
int on_recv_message_callback(int int_fd, int int_epfd); int main()
{
//初始化socket
int int_sfd = socket_init();
if (- == int_sfd)
{
printf("socket init fail...\n");
return -;
} //初始化epoll
int int_epfd = epoll_init(int_sfd); //进入epoll循环
epoll_loop(int_sfd, int_epfd); } int socket_init()
{
//初始化socket
int int_sfd = socket(AF_INET,SOCK_STREAM,);
int int_ret; //绑定ip、port
char pst_ip[] = "127.0.0.1";
struct sockaddr_in sock_server;
sock_server.sin_family = AF_INET;
sock_server.sin_addr.s_addr = inet_addr(pst_ip);
short int_16_port;
for(int_16_port = ; int_16_port < ; ++int_16_port)
{
sock_server.sin_port = htons(int_16_port);
int_ret = bind(int_sfd, (struct sockaddr*)&sock_server, sizeof(struct sockaddr));
if(- == int_ret)
{
printf("bind port = %d fail..retry!\n",int_16_port);
continue;
}
break;
} if(- == int_ret)
{
perror("bind");
return -;
}
printf("bind port = %d success!\n",int_16_port); //监听
int_ret = listen(int_sfd, );
if(- == int_ret)
{
perror("listen");
return -;
} return int_sfd;
} int epoll_add(int int_fd, int int_epfd)
{
struct epoll_event epoll_ev;
epoll_ev.events = EPOLLIN|EPOLLET;
epoll_ev.data.fd = int_fd;
epoll_ctl(int_epfd, EPOLL_CTL_ADD, int_fd, &epoll_ev);
return ;
} int epoll_del(int int_fd, int int_epfd)
{
struct epoll_event epoll_ev;
epoll_ev.events = EPOLLIN|EPOLLET;
epoll_ev.data.fd = int_fd;
epoll_ctl(int_epfd, EPOLL_CTL_DEL, int_fd, &epoll_ev);
printf("close fd = %d\n", int_fd);
close(int_fd);
return ;
} int epoll_init(int int_sfd)
{
int int_epfd;
int_epfd = epoll_create();
epoll_add(int_sfd, int_epfd);
return int_epfd; } int on_accept_callback(int int_sfd, int int_epfd)
{
struct sockaddr_in sock_client;
socklen_t sock_len; //接入客户端
int int_new_fd = accept(int_sfd, (struct sockaddr*)&sock_client, &sock_len);
if(- == int_new_fd)
{
perror("accept");
return -;
} //把new_fd注册到epfd中
epoll_add(int_new_fd, int_epfd); //修改文件描述符状态为非阻塞
int int_status=fcntl(int_new_fd,F_GETFL);
int_status=int_status|O_NONBLOCK;
fcntl(int_new_fd,F_SETFL,int_status); printf("accept new_fd = %d success!\n", int_new_fd);
return int_new_fd;
} int on_recv_message_callback(int int_fd, int int_epfd)
{
printf("recv msg from fd = %d\n", int_fd);
char pst_buffer[];
int int_ret;
while()
{
memset(pst_buffer, , sizeof(pst_buffer));
int_ret = recv(int_fd, (void*)pst_buffer, sizeof(pst_buffer) - , );
if( > int_ret)
{
break;
}
if( == int_ret)
{
printf("The client has been offline\n");
epoll_del(int_fd, int_epfd);
return -;
}
printf("%s", pst_buffer);
}
printf("\n"); char pst_msg[] = "The server has recv your message...";
printf("%ld\n", sizeof(pst_msg)); int_ret = send(int_fd, (void*)pst_msg, sizeof(pst_msg) - , );
if(- == int_ret)
{
perror("send msg");
epoll_del(int_fd,int_epfd);
return -;
}
printf("%d\n", int_ret); return ;
} int epoll_loop(int int_sfd, int int_epfd)
{
struct epoll_event epoll_evs[];
int int_ret;
int int_event_num;
int int_idx;
printf("loop....\n"); //循环体
while()
{
memset(epoll_evs, , sizeof(epoll_evs)); //等待事件
int_event_num = epoll_wait(int_epfd, epoll_evs, , -);
if (int_event_num > )
{
for(int_idx = ; int_idx < int_event_num; ++int_idx)
{
if(epoll_evs[int_idx].events == EPOLLIN)
{
if(epoll_evs[int_idx].data.fd == int_sfd)
{
//有新客户端要接入
int_ret = on_accept_callback(int_sfd, int_epfd);
if(- == int_ret)
{
printf("on accept callback fail...\n");
continue;
}
}
else
{
//收到来自客户端的消息
int_ret = on_recv_message_callback(epoll_evs[int_idx].data.fd, int_epfd);
if(- == int_ret)
{
printf("on recv message callback fail...\n");
continue;
}
}
}
}
}
}
}

使用libevent:

只需要写回调函数,然后添加到监听的事件集合里就行了。就使用上来说,还是很方便的。

client.c

  ///
/// @file client.c
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-10-23 21:27:33
/// #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <event.h> int socket_init(char * pst_ip, short short_port);
void on_send_message_callback(int int_fd, __attribute__((unused)) short short_events, void *arg);
void on_recv_message_callback(int int_fd, __attribute__((unused)) short short_events, __attribute__((unused)) void *arg); int main(int argc, char* argv[])
{
if(argc != )
{
printf("%s ip port\n",argv[]);
return -;
} char * pst_ip = argv[];
short short_port = atoi(argv[]); //初始化socket
int int_sfd = socket_init(pst_ip, short_port);
if (- == int_sfd)
{
printf("socket init fail...\n");
return -;
} //添加监听服务器消息事件
struct event_base * base = event_base_new();
struct event* event_recv_msg = event_new(base, int_sfd, EV_READ|EV_PERSIST, on_recv_message_callback, NULL);
event_add(event_recv_msg, NULL); //添加监听终端输入事件
struct event* event_send_msg = event_new(base, STDIN_FILENO, EV_READ|EV_PERSIST, on_send_message_callback, (void*)&int_sfd);
event_add(event_send_msg, NULL); //进入循环
event_base_dispatch(base); return ;
} void on_send_message_callback(int int_fd, __attribute__((unused)) short short_events, void *arg)
{
char pst_buffer[];
int int_ret;
int int_socket_fd = *(int*)arg;
memset(pst_buffer, , sizeof(pst_buffer));
int_ret = read(int_fd, pst_buffer, sizeof(pst_buffer) - );
printf("input = %s; ret = %d\n", pst_buffer, int_ret);
if( == int_ret)
{
printf("bye~\n");
exit(-);
} else
{
printf("send = %s\n", pst_buffer);
int_ret = write(int_socket_fd, (void*)pst_buffer, sizeof(pst_buffer) - );
if(- == int_ret)
{
perror("send");
exit(-);
}
printf("send success!\n");
}
} void on_recv_message_callback(int int_fd, __attribute__((unused)) short short_events, __attribute__((unused)) void *arg)
{
char pst_buffer[];
int int_ret;
while()
{
memset(pst_buffer, , sizeof(pst_buffer));
int_ret = recv(int_fd, (void*)pst_buffer, sizeof(pst_buffer) - , );
if( > int_ret)
{
break;
}
if( == int_ret)
{
printf("The server has been offline\n");
exit(-);
}
printf("%s", pst_buffer);
}
printf("\n");
} int socket_init(char * pst_ip, short short_port)
{
int int_sfd = socket(AF_INET,SOCK_STREAM,);
if(- == int_sfd)
{
perror("socket");
return -;
}
int int_ret; struct sockaddr_in sock_client;
sock_client.sin_family = AF_INET;
sock_client.sin_addr.s_addr = inet_addr(pst_ip);
sock_client.sin_port = htons(short_port); printf("prepare to connect ip:%s port:%d\n", pst_ip, short_port);
int_ret = connect(int_sfd, (struct sockaddr*)&sock_client, sizeof(sock_client));
if(- == int_ret)
{
perror("connect");
return -;
}
printf("connect ip:%s port:%d success!\n", pst_ip, short_port);
evutil_make_socket_nonblocking(int_sfd);
return int_sfd;
}

server.c

  ///
/// @file server.c
/// @author marrs(chenchengxi993@gmail.com)
/// @date 2017-10-22 19:58:15
/// #include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <event.h>
#include <arpa/inet.h> int socket_init();
void on_accept_callback(int int_fd, __attribute__((unused)) short short_events, void *arg);
void on_recv_message(int int_fd, __attribute__((unused)) short short_events, void *arg); int main()
{
//初始化socket
int int_sfd = socket_init();
if(- == int_sfd)
{
printf("socket init fail...\n");
return -;
} //初始化struct event_base对象
struct event_base * base = event_base_new(); //添加监听客户端请求连接事件
struct event* event_listen = event_new(base, int_sfd, EV_READ|EV_PERSIST, on_accept_callback, base);
event_add(event_listen, NULL); //进入循环
event_base_dispatch(base); } int socket_init()
{
int int_ret;
short short_port;
struct sockaddr_in sock_server; //初始化socket
evutil_socket_t socket_fd = socket(AF_INET, SOCK_STREAM, );
if(- == socket_fd)
{
goto error;
}
printf("get socket fd success\n"); //允许多次绑定同一个地址
evutil_make_listen_socket_reuseable(socket_fd); //绑定ip、port
sock_server.sin_family = AF_INET;
sock_server.sin_addr.s_addr = ;
for(short_port = ; short_port < ; ++short_port)
{
sock_server.sin_port = htons(short_port);
int_ret = bind(socket_fd, (struct sockaddr*)&sock_server, sizeof(sock_server));
if(- == int_ret)
{
continue;
}
break;
}
if(- == int_ret)
{
goto error;
} printf("bind port = %d success\n", short_port); //监听
int_ret = listen(socket_fd, );
if(- == int_ret)
{
goto error;
}
printf("listen success\n"); //修改文件描述符状态为非阻塞
evutil_make_socket_nonblocking(socket_fd);
return socket_fd; //error
error:
perror("socket init");
evutil_closesocket(socket_fd);
return -;
} void on_accept_callback(int int_fd, __attribute__((unused))short short_events, void *arg)
{
evutil_socket_t socket_fd;
struct sockaddr_in sock_client;
socklen_t sock_len; //接入
socket_fd = accept(int_fd, (struct sockaddr*)&sock_client, &sock_len);
if(- == socket_fd)
{
perror("accept");
return;
}
printf("accpet a new client...\n"); //修改文件描述符状态为非阻塞
evutil_make_socket_nonblocking(socket_fd); //添加监听客户端发送消息事件
struct event_base* base = (struct event_base*)arg;
struct event* event_client = event_new(NULL, -, , NULL, NULL);
event_assign(event_client, base, socket_fd, EV_READ|EV_PERSIST, on_recv_message, (void*)event_client);
event_add(event_client, NULL); } void on_recv_message(int int_fd, __attribute__((unused))short short_events, void *arg)
{
char pst_buffer[];
int int_ret;
struct event *event_client = (struct event*)arg;
while()
{
memset(pst_buffer, , sizeof(pst_buffer));
int_ret = read(int_fd, (void*)pst_buffer, sizeof(pst_buffer) - );
if( == int_ret)
{
printf("the client has been offline...\n");
event_free(event_client);
close(int_fd);
return;
}
else if( > int_ret)
{
break;
}
else
{
printf("%s", pst_buffer);
}
}
printf("\n"); char pst_msg[] = "the server has recv your msg....";
int_ret = write(int_fd, pst_msg, strlen(pst_msg));
}

libevent学习笔记 —— 牛刀小试:简易的服务器的更多相关文章

  1. libevent学习笔记 一、基础知识【转】

    转自:https://blog.csdn.net/majianfei1023/article/details/46485705 欢迎转载,转载请注明原文地址:http://blog.csdn.net/ ...

  2. 【传智播客】Libevent学习笔记(一):简介和安装

    目录 00. 目录 01. libevent简介 02. Libevent的好处 03. Libevent的安装和测试 04. Libevent成功案例 00. 目录 @ 01. libevent简介 ...

  3. Libevent学习笔记

    学习: /Users/baidu/Documents/Data/Interview/服务器-检索端/libevent参考手册(中文版).pdf 讲的不好.翻译的..

  4. Vue.js 学习笔记之三:与服务器的数据交互

    显而易见的,之前的02_toDoList存在着一个很致命的缺陷.那就是它的数据只存在于浏览器端,一但用户关闭或重新载入页面,他之前加入到程序中的数据就会全部丢失,一切又恢复到程序的初始状态.要想解决这 ...

  5. linux网络编程学习笔记之四 -----多-threaded服务器

    对于使用过程中并发.通过实现更轻量级线程. 每个线程都是一个独立的逻辑流. 主题是CPU在执行调度的最小独立单位,这个过程是资源分配单元.当然,这是在微内核操作系统说.总之,这是唯一的一个操作系统内核 ...

  6. Android学习笔记————利用JDBC连接服务器数据库

    /******************************************************************************************** * auth ...

  7. Libevent学习笔记(五) 根据例子学习bufferevent

    libevent中提供了一个Hello-world.c 的例子,从这个例子可以学习libevent是如何使用bufferevent的. 这个例子在Sample中 这个例子之前讲解过,这次主要看下buf ...

  8. libevent学习笔记(参考libevent深度剖析)

    最近自学libevent事件驱动库,参考的资料为libevent2.2版本以及张亮提供的<Libevent源码深度剖析>, 参考资料: http://blog.csdn.net/spark ...

  9. 【传智播客】Libevent学习笔记(三):事件循环

    目录 00. 目录 01. event_base_loop函数 02. event_base_dispatch函数 03. event_base_loopexit函数 04. event_base_l ...

随机推荐

  1. 前端传给后端的数据类型为ImmutableMultiDict 咋办

    https://segmentfault.com/q/1010000002802028 偷得人家的答案     以下是解决办法:::: -------------------------------- ...

  2. mysql 多实例

    linux系统下,先用mysql用户帐号的身份建立数据表:/usr/local/webserver/mysql/bin/mysql_install_db --basedir=/usr/local/we ...

  3. Haproxy搭建Web群集

    一.Haproxy与LVS LVS不支持正则处理,不能实现动静分离,对于大型网站,LVS的实施配置复杂,维护成本相对较高 Harpoxy是一款可提供高可用性,负载均衡.及基于TCP和HTTP应用的代理 ...

  4. 本机号码认证黑科技:极光(JG)开发者服务推出“极光认证”新产品

    近日,中国领先的大数据服务商极光(JG)推出全新产品--极光认证JVerification.极光认证是极光针对APP用户注册登陆,二次安全验证等身份验证场景打造的一款本机号码认证SDK,验证用户提供的 ...

  5. centos启动错误:Inodes that were part of a corrupted orphan linked list found.

    centos启动时,提示错误: /dev/mapper/VolGroup-lv_root contains a file system with errors,check forced. /dev/m ...

  6. 对Routers的理解

    路由Routers 对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息. REST framework提供 ...

  7. Python库大全

    网络 urllib -网络库(stdlib). requests -网络库. grab – 网络库(基于pycurl). pycurl – 网络库(绑定libcurl). urllib3 – Pyth ...

  8. HAL库PWM

    1.占空比控制 a.在CUBMX的TIM下选择时钟源,选择通道为模式PWM Generation ch1 ,设置分频系数,初始值,不需要自动重装载,选择PWM模式1或2,设置比较值pulse,设置初始 ...

  9. poj3250 Bad Hair Day 单调栈(递减)

    Bad Hair Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 24420   Accepted: 8292 Des ...

  10. HLS:OpenCV和RTL代码转换关系

    OpenCV 图像处理是基于存储器帧缓存而构建的, 它总是假设视频帧数据存放在外部 DDR 存储器中. 由于处理器的小容量高速缓存性能的限制, 因此, OpenCV 访问局部图像性能较差. 并且, 从 ...