/* 原创文章 转载请附上原链接: 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 服务器相关推荐

  1. mysql 花生壳 2003_基于HTTP协议实现的小型web服务器的方法

    这篇文章主要介绍了基于HTTP协议实现的小型web服务器的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 我们先了解一下这个 ...

  2. linux线程池实现多线程并发,基于Linux的多线程池并发Web服务器设计-电子设计工程.PDF...

    基于Linux的多线程池并发Web服务器设计-电子设计工程.PDF 第 卷 第 期 电子设计工程 年 月 基于 的多线程池并发 服务器设计 陈 涛 任海兰 武汉邮电科学研究院 湖北 武汉 摘要 时至今 ...

  3. 基于安卓手机使用Termux搭建web服务器教程

    基于安卓手机使用Termux搭建web服务器教程 一.软件的准备 Termux Android5.0以上的手机(最好root) Xshell 6(windows软件) 二.前期Termux的设置与安装 ...

  4. 网络云存储技术Windows server 2012 (项目二十 一 基于Cluster的高可用企业WEB服务器的部署)

    网络云存储技术Windows server 2012 (项目二十一 基于Cluster的高可用企业WEB服务器的部署) 前言 网络存储技术,是以互联网为载体实现数据的传输与存储,它采用面向网络的存储体 ...

  5. Fenix – 基于 Node.js 的桌面静态 Web 服务器

    Fenix 是一个提供给开发人员使用的简单的桌面静态 Web 服务器,基于 Node.js 开发.您可以同时在上面运行任意数量的项目,特别适合前端开发人员使用. 您可以通过免费的 Node.js 控制 ...

  6. 免费开源的几款Web服务器软件简介

    由于最近在部署云服务器主机,在对Web服务器软件的选型方面进行了摸索,把笔记记下来,便于以后查阅. 一.NGINX 俄罗斯人Igor Sysoev从2002年开始开发NGINX,并在2004年发布了第 ...

  7. 基于HTTP协议实现的小型web服务器

    我们先了解一下这个项目最终能达到的一个目标,然后以这个来进行项目的分析: 1.实现最基本的HTTP/1.0版本的web服务器,客户端能够使用GET.POST方法请求资源 2.服务器将客户请求的资源以h ...

  8. (chap9 基于HTTP的功能追加协议) Web 服务器管理文件的 WebDAV

    WebDAV(Web-based Distributed Authoring and Versioning)基于万维网的分布式创作和版本控制 1. 定义 一个可对 Web 服务器上的内容直接进行文件复 ...

  9. web sqlite linux,基于嵌入式Linux和Sqlite的Web服务器的研究及应用

    摘要: 嵌入式设备凭借其性能高,体积小,低功耗等优点出现在我们生活的方方面面中.同时,随着互联网迅速普及,嵌入式设备与互联网的结合成为了嵌入式设备发展的一种趋势,并成就了嵌入式设备的远程监控管理等复杂 ...

  10. termux运行python文件知乎_(萌新、小白看过来!)最详细、完整的基于安卓手机使用Termux搭建web服务器教程!...

    三.Termux搭建WEB服务器所需的软件及配置(分3步,Termux中下载) 1.php a.下载php pkg install php b.开启php自带的web服务器并指定建站系统文件夹(-t ...

最新文章

  1. Spring cloud 微服务docker容器化最佳实践
  2. 漫画 | 如何向外行解释产品经理频繁更改需求会令程序员很焦灼?
  3. 解决:请购买WinRAR许可,您注册还剩下40天(WinRAR老是弹出烦人的对话框)
  4. 计算机应用教程 中级 平装,计算机应用中级教程
  5. 新版pycharm,亮瞎我的狗眼
  6. 怎样在计算机上插入机构图,Win7系统如何在excel中添加word文档结构图?
  7. 如何高效备考信息系统项目管理师?
  8. C# Httpclient编程
  9. HDU - 5790 Prefix(主席树+字典树)
  10. 因此,Oracle杀死了java.net
  11. fpga板子怎么和电脑连_windows7台式电脑怎么连接路由器?台式win7电脑连路由器步骤...
  12. sqlplus几个存储过程执行变量值窜掉了_单片机必知的数据存储与程序编写知识!...
  13. 携程机器学习开发部署一体化平台实践之路
  14. linux mysql免安装版配置_Linux下MySQL免安装版安装配置记录
  15. [转]尺度不变特征变换(SIFT算法)Matlab程序代码测试例子的说明(Lowe的代码)
  16. Zabbix监控流量异常(偶尔超出交换机限制)
  17. 2021年茶艺师(中级)考试及茶艺师(中级)考试题
  18. 高德地图——货车导航
  19. 测试面试题——三角形
  20. 谷粒商城 -->「P01-P44」

热门文章

  1. 简单总结一下JS的Array对象
  2. WAF Bypass数据库特性(Oracle探索篇)
  3. [Deep Learning] 神经网络基础
  4. No_16_0224 Java基础学习第五天
  5. ios sinaweibo 客户端(二)
  6. 九大CTO畅谈软件定义未来
  7. android编译make错误——javalib.jar invalid header field”、classes-full-debug.jar 错误 41 ...
  8. linux下高可用性群集和负载均衡群集的实现
  9. [patterns practices] Web 服务安全:场景、模式和实现指南
  10. 从备用类型总盗用steal page