/* 原创文章 转载请附上原链接: */
自己实现的如有缺漏欢迎提出
直接代码 一切皆在代码中
首先是 主函数文件 和 头文件
头文件:
1 #ifndef _HEAD_H_ 2 #define _HEAD_H_ 3 4 #include5 #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
主函数文件:
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 }
接下来是 调用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 }
然后是 发送文件和目录的回调“
文件的:
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 }
目录的(这里拼接网页的时候要细心 非常细心的那种 ):
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 \21Curent dir:%s \22 \23 \24Curretn Dir Content:%s
\25d_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 "
Name | Size | Type | \28
%s | \50%ld | \51%s | \52
最后就是一些小函数了: 判断文件类型 和是否为目录:
判断文件类型(这里如果出问题 打开图片等时会出现问题):
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 }
判断是否为目录:
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
注:以上代码已测验,基本没有问题(bug 肯定有 欢迎提出)
结语:有问题欢迎提在下方 ,本人在校学生,时间较为充裕, 有时间会回复的。
/* 原创文章 转载请附上原链接: */