回想起之前自己用纯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. 【3】JMicro微服务-服务超时,重试,重试间隔

    如非授权,禁止用于商业用途,转载请注明出处作者:mynewworldyyl 接下来的内容都基于[2]JMicro微服务-Hello World做Demo 微服务中,超时和重试是一个最基本问题下面Dem ...

  2. 手动抠下的wordpress登录页面样式

    CSS文件 login.css body, html { height: 100%; margin: 0; padding: 0; } html[Attributes Style] { -webkit ...

  3. SVN服务器端环境搭建步骤

    5.1 安装服务器端程序 yum install -y subversion 5.2 创建并配置版本库 创建版本库目录 mkdir -p /var/svn/repository 在版本库目录下创建具体 ...

  4. 启动多个appium服务(同时运行多台设备)

    准备: 一台真机一台模拟器(使用的是“夜神模拟器”) 先查看是否检测到设备  adb devices    由上图可看出没有检测到模拟器(夜神模拟器已开启) 可通过以下配置完成: 第一步:找到adb的 ...

  5. python之守护进程

    主进程创建子进程,然后将该进程设置成守护自己的进程,守护进程就好比崇祯皇帝身边的老太监,崇祯皇帝已死老太监就跟着殉葬了. 关于守护进程需要强调两点: 其一:守护进程会在主进程代码执行结束后就终止 其二 ...

  6. TP5 隐藏入口文件 index.php

    找到public下的.htaccess <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine ...

  7. Flask-mail 发邮件慢(即使异步)

    Flask-mail 发邮件慢(即使异步) 一开始,按照狗书上的代码异步发邮件,但是发现原本响应只需要150ms的页面加了邮件发送就变成了5s响应(这怕不是假异步) 狗书的异步发邮件代码: def s ...

  8. js img转换base64

    方法一:canvas <script type="text/javascript"> function getBase64Image(img) { var canvas ...

  9. Q221 最大正方形

    在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积. 示例: 输入: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 输出: 4 cla ...

  10. gradle 打包 jar (一波三折)

    第一次尝试,打包成功,运行失败 build.gradle 打包 jar { baseName 'testJar' from { //添加依懒到打包文件 //configurations.compile ...