博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于 libevent 开源框架实现的 web 服务器
阅读量:6229 次
发布时间:2019-06-21

本文共 11091 字,大约阅读时间需要 36 分钟。

/* 原创文章 转载请附上原链接:    */

自己实现的如有缺漏欢迎提出

直接代码 一切皆在代码中 

首先是 主函数文件 和 头文件

  头文件: 

1 #ifndef _HEAD_H_ 2 #define _HEAD_H_ 3  4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14 #include
15 #include
16 #include
17 #include
18 #include
19 #include
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     else23     {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
>%s\n",file); 25 send_file(bufev,file); 26 } 27 if(isFile == 1){
//is dir 28 printf("send dir
>%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
>%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 head18     sprintf(buf_dir_html,"\19                                 \20                                     \21                                         Curent dir:%s\22                                     \23                                     \24                                         

Curretn Dir Content:%s

\25
d_name);37 }38 else39 {40 sprintf(buf_current_name,"%s/%s",dirname,ptr[i]->d_name);41 }42 printf("++++++++++++++++++++send cur dir
>%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 "
\26
\27
\28
",dirname,dirname);29 bufferevent_write(bufev,buf_dir_html,strlen(buf_dir_html));30 31 for(int i=0;i
\49
\50
\51
\52
",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 end61 sprintf(buf_dir_html,62 "
Name Size Type
%s %ld %s
\63 \64 ");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     else24     {25         return 2;26     }27 28 }29 30 31 #if 032 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

你可能感兴趣的文章
我的网站搭建 (第十八天) 自定义用户模型
查看>>
排序应该在数据库还是在应用程序中进行?
查看>>
java过滤特殊字符的正则表达式,正则表达式学习
查看>>
VM VirtualBox安装CentOS 7 64位实践
查看>>
如何搭建一个独立博客——简明Github Pages与Hexo教程
查看>>
OC中Category的注意点
查看>>
OC中的布局-九宫格
查看>>
JAVA网络编程:计算机原理学习
查看>>
ARouter解析三:URL跳转本地页面源码分析
查看>>
git 常用操作
查看>>
iReport 中创建JavaBeanDataSource,用java类提供数据源给iReport
查看>>
大数据时代下的生活
查看>>
spring定时任务(方便轻巧)
查看>>
iOS的主要框架介绍
查看>>
spring源码阅读笔记(一)
查看>>
Selenium的简单安装和使用
查看>>
ios 滤镜
查看>>
linux系统学习第七天-<<工程师技术>>
查看>>
android中利用socket上传文件
查看>>
使用scrapy的定制爬虫-第二章-概
查看>>