基于 libevent 开源框架实现的 web 服务器
/* 原创文章 转载请附上原链接: https://www.cnblogs.com/jiujue/p/10707153.html */
自己实现的如有缺漏欢迎提出
直接代码 一切皆在代码中
首先是 主函数文件 和 头文件
头文件:
1 #ifndef _HEAD_H_ 2 #define _HEAD_H_ 3 4 #include<stdio.h> 5 #include<string.h> 6 #include<stdlib.h> 7 #include<time.h> 8 #include<math.h> 9 #include <fcntl.h> 10 #include <ctype.h> 11 #include <dirent.h> 12 #include <unistd.h> 13 #include <event2/event.h> 14 #include <event2/listener.h> 15 #include <event2/bufferevent.h> 16 #include <sys/socket.h> 17 #include <sys/types.h> 18 #include <sys/stat.h> 19 #include <arpa/inet.h> 20 21 int judge_type_dir_or_nondir(const char* name); 22 int send_dir_asheml(struct bufferevent *bufev, char *dirname, void *arg); 23 struct evconnlistener* libev_start(struct event_base*base, const char* Ip,int Port); 24 int send_html_head(struct bufferevent* bufev, int stat_no, const char* stat_desc, char* type); 25 const char *get_file_type(const char *name); 26 int send_file(struct bufferevent *bufev,char* file); 27 28 #endif
View Code
主函数文件:
1 // File Name: main.c 2 // Author: jiujue 3 // Created Time: 2019年04月05日 星期五 19时54分48秒 4 5 #include "head.h" 6 7 int main(int argc, const char* argv[]) 8 { 9 if(argc < 4) 10 { 11 printf("argument not enough\neg:./app Ip Port sourceDir\n"); 12 exit(1); 13 } 14 15 16 int ret = chdir(argv[3]); 17 if(-1 == ret) 18 { 19 perror("chdir error"); 20 exit(1); 21 } 22 else 23 { 24 printf("chdir successful,to -> %s\n",argv[3]); 25 } 26 27 struct event_base* base = event_base_new(); 28 29 struct evconnlistener* listen = libev_start(base,argv[1],atoi(argv[2])); 30 31 event_base_dispatch(base); 32 33 evconnlistener_free(listen); 34 event_base_free(base); 35 36 return 0 ; 37 }
View Code
接下来是 调用libevent框架了 (重头戏来了 注意回调的设置哦):
1 // File Name: _libev.c 2 // Author: jiujue 3 // Created Time: 2019年04月05日 星期五 19时54分08秒 4 #include "head.h" 5 #define PATH_OF_404_ "404.html" 6 7 void read_cb(struct bufferevent* bufev, void* arg) 8 { 9 printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<,,Happen read_cb\n"); 10 char buf[1024] = {0}, method[12] = {0}, path[1024] = {0}, protocol[12] = {0}; 11 bufferevent_read(bufev,buf,sizeof(buf)); 12 //printf("-----------------------recv http request :%s\n",buf); 13 sscanf(buf,"%s %s %s",method,path,protocol); 14 char *file = path+1; 15 if(0 == (strcmp(path,"/") ) ) 16 { 17 file = (char*)"./"; 18 } 19 20 int isFile = judge_type_dir_or_nondir(file); 21 printf("fffffffff is %d \n",isFile); 22 if(0 == isFile) 23 {//is palin file 24 printf("send file <name>>%s\n",file); 25 send_file(bufev,file); 26 } 27 if(isFile == 1){//is dir 28 printf("send dir <name>>%s\n",file); 29 send_html_head(bufev,200,"OK",(char*)"text/html"); 30 send_dir_asheml(bufev,file,NULL); 31 } 32 else if(-1 == isFile) 33 {//is not found file or directory 34 printf("send 404 <name>>%s\n",file); 35 send_file(bufev,PATH_OF_404_); 36 } 37 38 } 39 40 void write_cb(struct bufferevent* bufev, void* arg) 41 { 42 struct sockaddr_in *cli = (struct sockaddr_in*)arg; 43 char buf[1024] = {0}; 44 printf("Sent respond to cli,Ip ->%s and Port ->%d\n", 45 inet_ntop(AF_INET,&(cli->sin_addr.s_addr), buf,sizeof(buf)), 46 ntohs(cli->sin_port) ); 47 } 48 49 void event_cb(struct bufferevent* bufev, short ev, void* arg) 50 { 51 printf("event_cb successful\n"); 52 if(ev & BEV_EVENT_EOF) 53 { 54 struct sockaddr_in *cli = (struct sockaddr_in*)arg; 55 char buf[1024] = {0}; 56 printf("Have client disconnect, Ip ->%s and Port ->%d\n", 57 inet_ntop(AF_INET,&(cli->sin_addr.s_addr), buf,sizeof(buf)), 58 ntohs(cli->sin_port) ); 59 60 } 61 if(ev & BEV_EVENT_ERROR ) 62 { 63 printf("******************************** Happy Error******************************\n"); 64 } 65 bufferevent_free(bufev); 66 } 67 68 void listener_cb(struct evconnlistener *listener, 69 evutil_socket_t fd, struct sockaddr* cli, 70 int cli_len, void* arg) 71 { 72 73 printf("<<<<<<<<<<<<<<<<<<<<,,,,,,,,, listener_cb successful\n"); 74 struct event_base* base = (struct event_base*)arg; 75 76 struct bufferevent* bufev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); 77 bufferevent_setcb(bufev, read_cb, write_cb, event_cb,cli); 78 bufferevent_enable(bufev,EV_READ); 79 80 } 81 82 83 struct evconnlistener* libev_start(struct event_base*base, const char* Ip,int Port) 84 { 85 86 struct sockaddr_in ser; 87 ser.sin_family = AF_INET; 88 ser.sin_port = htons(Port); 89 inet_pton(AF_INET,Ip,&(ser.sin_addr.s_addr)); 90 91 struct evconnlistener* ret = evconnlistener_new_bind(base, listener_cb, base, 92 LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, 128, 93 (struct sockaddr *)&ser, sizeof(ser)); 94 95 if(ret == NULL) 96 { 97 return NULL; 98 } 99 100 return ret; 101 }
View Code
然后是 发送文件和目录的回调“
文件的:
1 #include "head.h" 2 3 int send_file(struct bufferevent *bufev,char* file) 4 { 5 6 7 int ffd = open(file,O_RDONLY); 8 if(-1 == ffd) 9 { 10 printf("sourceFilePath : %s\n",file); 11 perror("open sourceFile error"); 12 13 } 14 15 char file_read_buf[1024]; 16 int read_len = 0; 17 18 char * type = get_file_type(file); 19 20 21 send_html_head(bufev,200, "OK", type); 22 23 while((read_len=read(ffd, file_read_buf,sizeof(file_read_buf))) > 0) 24 { 25 if(0 == read_len) 26 { 27 break; 28 } 29 bufferevent_write(bufev,file_read_buf,read_len);; 30 file_read_buf[strlen(file_read_buf)+1] = '\n'; 31 printf("send message :%s\n",file_read_buf); 32 memset(file_read_buf,0,sizeof(file_read_buf)); 33 } 34 35 printf("close ...\n"); 36 close(ffd); 37 return 0; 38 }
View Code
目录的(这里拼接网页的时候要细心 非常细心的那种 ):
1 // File Name: _send_dir.c 2 // Author: jiujue 3 // Created Time: 2019年04月05日 星期五 19时27分18秒 4 5 #include "head.h" 6 #define MAXFORGTML_ 4096 7 8 9 int send_dir_asheml(struct bufferevent *bufev, char *dirname, void* arg) 10 { 11 printf("******************send_dir name is %s\n",dirname); 12 13 char* buf_dir_html = (char *)malloc(MAXFORGTML_); 14 struct dirent **ptr; 15 int dir_total_num = scandir(dirname,&ptr,NULL,alphasort); 16 17 //html head 18 sprintf(buf_dir_html,"<!doctype HTML>\ 19 <html>\ 20 <head>\ 21 <title>Curent dir:%s</title>\ 22 </head>\ 23 <body>\ 24 <h1>Curretn Dir Content:%s </h1>\ 25 <table>\ 26 <tr>\ 27 <td>Name</td><td>Size</td><td>Type</td>\ 28 </tr>",dirname,dirname); 29 bufferevent_write(bufev,buf_dir_html,strlen(buf_dir_html)); 30 31 for(int i=0;i<dir_total_num;++i) 32 { 33 char buf_current_name[1024] = {0}; 34 if( 0 == strcmp(dirname,"./")) 35 { 36 sprintf(buf_current_name,"%s%s",dirname,ptr[i]->d_name); 37 } 38 else 39 { 40 sprintf(buf_current_name,"%s/%s",dirname,ptr[i]->d_name); 41 } 42 printf("++++++++++++++++++++send cur dir <name>>%s\n",buf_current_name); 43 struct stat st; 44 memset(&st,0,sizeof(st)); 45 stat(buf_current_name,&st); 46 47 sprintf(buf_dir_html, 48 "<tr>\ 49 <td><a href=\"%s\">%s</a></td>\ 50 <td>%ld</td>\ 51 <td>%s</td>\ 52 </tr>", 53 buf_current_name, 54 ptr[i]->d_name,st.st_size, 55 judge_type_dir_or_nondir(buf_current_name)!= 0?"dir":"plain file"); 56 bufferevent_write(bufev,buf_dir_html,strlen(buf_dir_html)); 57 memset((char*)buf_dir_html,0,sizeof(buf_dir_html)); 58 } 59 60 //html end 61 sprintf(buf_dir_html, 62 "</table>\ 63 </body>\ 64 </html>"); 65 bufferevent_write(bufev,buf_dir_html,strlen(buf_dir_html)); 66 bufferevent_write(bufev,"\r\n",2); 67 68 free(buf_dir_html); 69 return 0; 70 }
View Code
最后就是一些小函数了: 判断文件类型 和是否为目录:
判断文件类型(这里如果出问题 打开图片等时会出现问题):
1 // File Name: _get_file_type.c 2 // Author: jiujue 3 // Created Time: 2019年04月06日 星期六 19时14分07秒 4 5 6 #include "head.h" 7 8 const char *get_file_type(const char *name) 9 { 10 char* dot; 11 12 13 dot = strrchr(name, '.'); 14 if (dot == NULL) 15 return "text/plain; charset=utf-8"; 16 if (strcmp(dot, ".html") == 0 || strcmp(dot, ".htm") == 0) 17 return "text/html; charset=utf-8"; 18 if (strcmp(dot, ".jpg") == 0 || strcmp(dot, ".jpeg") == 0) 19 return "image/jpeg"; 20 if (strcmp(dot, ".gif") == 0) 21 return "image/gif"; 22 if (strcmp(dot, ".png") == 0) 23 return "image/png"; 24 if (strcmp(dot, ".css") == 0) 25 return "text/css"; 26 if (strcmp(dot, ".au") == 0) 27 return "audio/basic"; 28 if (strcmp( dot, ".wav" ) == 0) 29 return "audio/wav"; 30 if (strcmp(dot, ".avi") == 0) 31 return "video/x-msvideo"; 32 if (strcmp(dot, ".mov") == 0 || strcmp(dot, ".qt") == 0) 33 return "video/quicktime"; 34 if (strcmp(dot, ".mpeg") == 0 || strcmp(dot, ".mpe") == 0) 35 return "video/mpeg"; 36 if (strcmp(dot, ".vrml") == 0 || strcmp(dot, ".wrl") == 0) 37 return "model/vrml"; 38 if (strcmp(dot, ".midi") == 0 || strcmp(dot, ".mid") == 0) 39 return "audio/midi"; 40 if (strcmp(dot, ".mp3") == 0) 41 return "audio/mpeg"; 42 if (strcmp(dot, ".ogg") == 0) 43 return "application/ogg"; 44 if (strcmp(dot, ".pac") == 0) 45 return "application/x-ns-proxy-autoconfig"; 46 47 return "text/plain; charset=utf-8"; 48 }
View Code
判断是否为目录:
1 // File Name: _judge_type.c 2 // Author: jiujue 3 // Created Time: 2019年04月05日 星期五 20时54分34秒 4 5 #include "head.h" 6 7 int judge_type_dir_or_nondir(const char* name) 8 { 9 struct stat st; 10 int ret = stat(name,&st); 11 if(-1 == ret) 12 { 13 return -1; 14 } 15 if(S_ISREG(st.st_mode)) 16 { 17 return 0; 18 } 19 if(S_ISDIR(st.st_mode)) 20 { 21 return 1; 22 } 23 else 24 { 25 return 2; 26 } 27 28 } 29 30 31 #if 0 32 int main(int argc,char* argv[]) 33 { 34 int ret = judge_type_dir_or_nondir(argv[1]); 35 if(ret == 1) 36 { 37 printf("is dir "); 38 } 39 if(ret == 0) 40 { 41 printf("is file"); 42 } 43 return 0; 44 } 45 #endif
View Code
注:以上代码已测验,基本没有问题(bug 肯定有 欢迎提出)
结语:有问题欢迎提在下方 ,本人在校学生,时间较为充裕, 有时间会回复的。
/* 原创文章 转载请附上原链接: https://www.cnblogs.com/jiujue/p/10707153.html */
转载于:https://www.cnblogs.com/jiujue/p/10707153.html
基于 libevent 开源框架实现的 web 服务器相关推荐
- mysql 花生壳 2003_基于HTTP协议实现的小型web服务器的方法
这篇文章主要介绍了基于HTTP协议实现的小型web服务器的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 我们先了解一下这个 ...
- linux线程池实现多线程并发,基于Linux的多线程池并发Web服务器设计-电子设计工程.PDF...
基于Linux的多线程池并发Web服务器设计-电子设计工程.PDF 第 卷 第 期 电子设计工程 年 月 基于 的多线程池并发 服务器设计 陈 涛 任海兰 武汉邮电科学研究院 湖北 武汉 摘要 时至今 ...
- 基于安卓手机使用Termux搭建web服务器教程
基于安卓手机使用Termux搭建web服务器教程 一.软件的准备 Termux Android5.0以上的手机(最好root) Xshell 6(windows软件) 二.前期Termux的设置与安装 ...
- 网络云存储技术Windows server 2012 (项目二十 一 基于Cluster的高可用企业WEB服务器的部署)
网络云存储技术Windows server 2012 (项目二十一 基于Cluster的高可用企业WEB服务器的部署) 前言 网络存储技术,是以互联网为载体实现数据的传输与存储,它采用面向网络的存储体 ...
- Fenix – 基于 Node.js 的桌面静态 Web 服务器
Fenix 是一个提供给开发人员使用的简单的桌面静态 Web 服务器,基于 Node.js 开发.您可以同时在上面运行任意数量的项目,特别适合前端开发人员使用. 您可以通过免费的 Node.js 控制 ...
- 免费开源的几款Web服务器软件简介
由于最近在部署云服务器主机,在对Web服务器软件的选型方面进行了摸索,把笔记记下来,便于以后查阅. 一.NGINX 俄罗斯人Igor Sysoev从2002年开始开发NGINX,并在2004年发布了第 ...
- 基于HTTP协议实现的小型web服务器
我们先了解一下这个项目最终能达到的一个目标,然后以这个来进行项目的分析: 1.实现最基本的HTTP/1.0版本的web服务器,客户端能够使用GET.POST方法请求资源 2.服务器将客户请求的资源以h ...
- (chap9 基于HTTP的功能追加协议) Web 服务器管理文件的 WebDAV
WebDAV(Web-based Distributed Authoring and Versioning)基于万维网的分布式创作和版本控制 1. 定义 一个可对 Web 服务器上的内容直接进行文件复 ...
- web sqlite linux,基于嵌入式Linux和Sqlite的Web服务器的研究及应用
摘要: 嵌入式设备凭借其性能高,体积小,低功耗等优点出现在我们生活的方方面面中.同时,随着互联网迅速普及,嵌入式设备与互联网的结合成为了嵌入式设备发展的一种趋势,并成就了嵌入式设备的远程监控管理等复杂 ...
- termux运行python文件知乎_(萌新、小白看过来!)最详细、完整的基于安卓手机使用Termux搭建web服务器教程!...
三.Termux搭建WEB服务器所需的软件及配置(分3步,Termux中下载) 1.php a.下载php pkg install php b.开启php自带的web服务器并指定建站系统文件夹(-t ...
最新文章
- Spring cloud 微服务docker容器化最佳实践
- 漫画 | 如何向外行解释产品经理频繁更改需求会令程序员很焦灼?
- 解决:请购买WinRAR许可,您注册还剩下40天(WinRAR老是弹出烦人的对话框)
- 计算机应用教程 中级 平装,计算机应用中级教程
- 新版pycharm,亮瞎我的狗眼
- 怎样在计算机上插入机构图,Win7系统如何在excel中添加word文档结构图?
- 如何高效备考信息系统项目管理师?
- C# Httpclient编程
- HDU - 5790 Prefix(主席树+字典树)
- 因此,Oracle杀死了java.net
- fpga板子怎么和电脑连_windows7台式电脑怎么连接路由器?台式win7电脑连路由器步骤...
- sqlplus几个存储过程执行变量值窜掉了_单片机必知的数据存储与程序编写知识!...
- 携程机器学习开发部署一体化平台实践之路
- linux mysql免安装版配置_Linux下MySQL免安装版安装配置记录
- [转]尺度不变特征变换(SIFT算法)Matlab程序代码测试例子的说明(Lowe的代码)
- Zabbix监控流量异常(偶尔超出交换机限制)
- 2021年茶艺师(中级)考试及茶艺师(中级)考试题
- 高德地图——货车导航
- 测试面试题——三角形
- 谷粒商城 -->「P01-P44」
热门文章
- 简单总结一下JS的Array对象
- WAF Bypass数据库特性(Oracle探索篇)
- [Deep Learning] 神经网络基础
- No_16_0224 Java基础学习第五天
- ios sinaweibo 客户端(二)
- 九大CTO畅谈软件定义未来
- android编译make错误——javalib.jar invalid header field”、classes-full-debug.jar 错误 41 ...
- linux下高可用性群集和负载均衡群集的实现
- [patterns practices] Web 服务安全:场景、模式和实现指南
- 从备用类型总盗用steal page