/* 原创文章 转载请附上原链接: https://www.cnblogs.com/jiujue/p/10707153.html   */

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

直接代码 一切皆在代码中

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

  头文件: 

 #ifndef _HEAD_H_
#define _HEAD_H_ #include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include <fcntl.h>
#include <ctype.h>
#include <dirent.h>
#include <unistd.h>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h> int judge_type_dir_or_nondir(const char* name);
int send_dir_asheml(struct bufferevent *bufev, char *dirname, void *arg);
struct evconnlistener* libev_start(struct event_base*base, const char* Ip,int Port);
int send_html_head(struct bufferevent* bufev, int stat_no, const char* stat_desc, char* type);
const char *get_file_type(const char *name);
int send_file(struct bufferevent *bufev,char* file); #endif

  主函数文件:

 // File Name: main.c
// Author: jiujue
// Created Time: 2019年04月05日 星期五 19时54分48秒 #include "head.h" int main(int argc, const char* argv[])
{
if(argc < )
{
printf("argument not enough\neg:./app Ip Port sourceDir\n");
exit();
} int ret = chdir(argv[]);
if(- == ret)
{
perror("chdir error");
exit();
}
else
{
printf("chdir successful,to -> %s\n",argv[]);
} struct event_base* base = event_base_new(); struct evconnlistener* listen = libev_start(base,argv[],atoi(argv[])); event_base_dispatch(base); evconnlistener_free(listen);
event_base_free(base); return ;
}

接下来是 调用libevent框架了 (重头戏来了 注意回调的设置哦):

 // File Name: _libev.c
// Author: jiujue
// Created Time: 2019年04月05日 星期五 19时54分08秒
#include "head.h"
#define PATH_OF_404_ "404.html" void read_cb(struct bufferevent* bufev, void* arg)
{
printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<,,Happen read_cb\n");
char buf[] = {}, method[] = {}, path[] = {}, protocol[] = {};
bufferevent_read(bufev,buf,sizeof(buf));
//printf("-----------------------recv http request :%s\n",buf);
sscanf(buf,"%s %s %s",method,path,protocol);
char *file = path+;
if( == (strcmp(path,"/") ) )
{
file = (char*)"./";
} int isFile = judge_type_dir_or_nondir(file);
printf("fffffffff is %d \n",isFile);
if( == isFile)
{//is palin file
printf("send file <name>>%s\n",file);
send_file(bufev,file);
}
if(isFile == ){//is dir
printf("send dir <name>>%s\n",file);
send_html_head(bufev,,"OK",(char*)"text/html");
send_dir_asheml(bufev,file,NULL);
}
else if(- == isFile)
{//is not found file or directory
printf("send 404 <name>>%s\n",file);
send_file(bufev,PATH_OF_404_);
} } void write_cb(struct bufferevent* bufev, void* arg)
{
struct sockaddr_in *cli = (struct sockaddr_in*)arg;
char buf[] = {};
printf("Sent respond to cli,Ip ->%s and Port ->%d\n",
inet_ntop(AF_INET,&(cli->sin_addr.s_addr), buf,sizeof(buf)),
ntohs(cli->sin_port) );
} void event_cb(struct bufferevent* bufev, short ev, void* arg)
{
printf("event_cb successful\n");
if(ev & BEV_EVENT_EOF)
{
struct sockaddr_in *cli = (struct sockaddr_in*)arg;
char buf[] = {};
printf("Have client disconnect, Ip ->%s and Port ->%d\n",
inet_ntop(AF_INET,&(cli->sin_addr.s_addr), buf,sizeof(buf)),
ntohs(cli->sin_port) ); }
if(ev & BEV_EVENT_ERROR )
{
printf("******************************** Happy Error******************************\n");
}
bufferevent_free(bufev);
} void listener_cb(struct evconnlistener *listener,
evutil_socket_t fd, struct sockaddr* cli,
int cli_len, void* arg)
{ printf("<<<<<<<<<<<<<<<<<<<<,,,,,,,,, listener_cb successful\n");
struct event_base* base = (struct event_base*)arg; struct bufferevent* bufev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bufev, read_cb, write_cb, event_cb,cli);
bufferevent_enable(bufev,EV_READ); } struct evconnlistener* libev_start(struct event_base*base, const char* Ip,int Port)
{ struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(Port);
inet_pton(AF_INET,Ip,&(ser.sin_addr.s_addr)); struct evconnlistener* ret = evconnlistener_new_bind(base, listener_cb, base,
LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, ,
(struct sockaddr *)&ser, sizeof(ser)); if(ret == NULL)
{
return NULL;
} return ret;
}

然后是 发送文件和目录的回调“

  文件的:

 #include "head.h"

 int send_file(struct bufferevent *bufev,char* file)
{ int ffd = open(file,O_RDONLY);
if(- == ffd)
{
printf("sourceFilePath : %s\n",file);
perror("open sourceFile error"); } char file_read_buf[];
int read_len = ; char * type = get_file_type(file); send_html_head(bufev,, "OK", type); while((read_len=read(ffd, file_read_buf,sizeof(file_read_buf))) > )
{
if( == read_len)
{
break;
}
bufferevent_write(bufev,file_read_buf,read_len);;
file_read_buf[strlen(file_read_buf)+] = '\n';
printf("send message :%s\n",file_read_buf);
memset(file_read_buf,,sizeof(file_read_buf));
} printf("close ...\n");
close(ffd);
return ;
}

  目录的(这里拼接网页的时候要细心 非常细心的那种 ):

 // File Name: _send_dir.c
// Author: jiujue
// Created Time: 2019年04月05日 星期五 19时27分18秒 #include "head.h"
#define MAXFORGTML_ 4096 int send_dir_asheml(struct bufferevent *bufev, char *dirname, void* arg)
{
printf("******************send_dir name is %s\n",dirname); char* buf_dir_html = (char *)malloc(MAXFORGTML_);
struct dirent **ptr;
int dir_total_num = scandir(dirname,&ptr,NULL,alphasort); //html head
sprintf(buf_dir_html,"<!doctype HTML>\
<html>\
<head>\
<title>Curent dir:%s</title>\
</head>\
<body>\
<h1>Curretn Dir Content:%s </h1>\
<table>\
<tr>\
<td>Name</td><td>Size</td><td>Type</td>\
</tr>",dirname,dirname);
bufferevent_write(bufev,buf_dir_html,strlen(buf_dir_html)); for(int i=;i<dir_total_num;++i)
{
char buf_current_name[] = {};
if( == strcmp(dirname,"./"))
{
sprintf(buf_current_name,"%s%s",dirname,ptr[i]->d_name);
}
else
{
sprintf(buf_current_name,"%s/%s",dirname,ptr[i]->d_name);
}
printf("++++++++++++++++++++send cur dir <name>>%s\n",buf_current_name);
struct stat st;
memset(&st,,sizeof(st));
stat(buf_current_name,&st); sprintf(buf_dir_html,
"<tr>\
<td><a href=\"%s\">%s</a></td>\
<td>%ld</td>\
<td>%s</td>\
</tr>",
buf_current_name,
ptr[i]->d_name,st.st_size,
judge_type_dir_or_nondir(buf_current_name)!= ?"dir":"plain file");
bufferevent_write(bufev,buf_dir_html,strlen(buf_dir_html));
memset((char*)buf_dir_html,,sizeof(buf_dir_html));
} //html end
sprintf(buf_dir_html,
"</table>\
</body>\
</html>");
bufferevent_write(bufev,buf_dir_html,strlen(buf_dir_html));
bufferevent_write(bufev,"\r\n",); free(buf_dir_html);
return ;
}

最后就是一些小函数了: 判断文件类型 和是否为目录:

  判断文件类型(这里如果出问题 打开图片等时会出现问题):

 // File Name: _get_file_type.c
// Author: jiujue
// Created Time: 2019年04月06日 星期六 19时14分07秒 #include "head.h" const char *get_file_type(const char *name)
{
char* dot; dot = strrchr(name, '.');
if (dot == NULL)
return "text/plain; charset=utf-8";
if (strcmp(dot, ".html") == || strcmp(dot, ".htm") == )
return "text/html; charset=utf-8";
if (strcmp(dot, ".jpg") == || strcmp(dot, ".jpeg") == )
return "image/jpeg";
if (strcmp(dot, ".gif") == )
return "image/gif";
if (strcmp(dot, ".png") == )
return "image/png";
if (strcmp(dot, ".css") == )
return "text/css";
if (strcmp(dot, ".au") == )
return "audio/basic";
if (strcmp( dot, ".wav" ) == )
return "audio/wav";
if (strcmp(dot, ".avi") == )
return "video/x-msvideo";
if (strcmp(dot, ".mov") == || strcmp(dot, ".qt") == )
return "video/quicktime";
if (strcmp(dot, ".mpeg") == || strcmp(dot, ".mpe") == )
return "video/mpeg";
if (strcmp(dot, ".vrml") == || strcmp(dot, ".wrl") == )
return "model/vrml";
if (strcmp(dot, ".midi") == || strcmp(dot, ".mid") == )
return "audio/midi";
if (strcmp(dot, ".mp3") == )
return "audio/mpeg";
if (strcmp(dot, ".ogg") == )
return "application/ogg";
if (strcmp(dot, ".pac") == )
return "application/x-ns-proxy-autoconfig"; return "text/plain; charset=utf-8";
}

  判断是否为目录:

 // File Name: _judge_type.c
// Author: jiujue
// Created Time: 2019年04月05日 星期五 20时54分34秒 #include "head.h" int judge_type_dir_or_nondir(const char* name)
{
struct stat st;
int ret = stat(name,&st);
if(- == ret)
{
return -;
}
if(S_ISREG(st.st_mode))
{
return ;
}
if(S_ISDIR(st.st_mode))
{
return ;
}
else
{
return ;
} } #if 0
int main(int argc,char* argv[])
{
int ret = judge_type_dir_or_nondir(argv[]);
if(ret == )
{
printf("is dir ");
}
if(ret == )
{
printf("is file");
}
return ;
}
#endif

注:以上代码已测验,基本没有问题(bug 肯定有 欢迎提出)

结语:有问题欢迎提在下方 ,本人在校学生,时间较为充裕, 有时间会回复的。

/* 原创文章 转载请附上原链接: https://www.cnblogs.com/jiujue/p/10707153.html   */

基于 libevent 开源框架实现的 web 服务器的更多相关文章

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

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

  2. 基于 libevent 开发的 C++ 11 高性能网络服务器 evpp(360的作品)

    evpp是一个基于libevent开发的现代化C++11高性能网络服务器,自带TCP/UDP/HTTP等协议的异步非阻塞式的服务器和客户端库. 特性: 现代版的C++11接口 非阻塞异步接口都是C++ ...

  3. 基于Java Mina框架的部标jt808服务器设计和开发

    在开发部标GPS平台中,部标jt808GPS服务器是系统的核心关键,决定了部标平台的稳定性和行那个.Linux服务器是首选,为了跨平台,开发语言选择Java自不待言.需要购买jt808GPS服务器源码 ...

  4. 基于Facebook开源框架SocketRocket的即时通讯

    SocketRocket 介绍: SocketRock 是 Facebook 开源的框架,基于 WebSocket 客户端类库,适用于 iOS.Mac OS.tv OS.GitHub 传送门:http ...

  5. 基于Java Mina框架的部标808服务器设计和开发

    在开发部标GPS平台中,部标808GPS服务器是系统的核心关键,决定了部标平台的稳定性和行那个.Linux服务器是首选,为了跨平台,开发语言选择Java自不待言. 我们为客户开发的部标服务器基于Min ...

  6. 基于corosync+pacemaker+drbd+LNMP做web服务器的高可用集群

    实验系统:CentOS 6.6_x86_64 实验前提: 1)提前准备好编译环境,防火墙和selinux都关闭: 2)本配置共有两个测试节点,分别coro1和coro2,对应的IP地址分别为192.1 ...

  7. 基于NPOI开源框架写的ExcelHelper【转载】

    namespace ExcelTest { using System; using System.Collections.Generic; using System.Data; using Syste ...

  8. springboot完整项目,基于人人开源框架

    这是前端和数据库 下载链接只有31天有效,需要的,请联系QQ2319899766 下载链接密码: 9ksz 这个是后端代码 链接只有31天有效时间,链接失效请联系QQ2319899766提供下载链接 ...

  9. TCP/IP协议学习(七) 基于C# Socket的Web服务器---动态通讯实现

    目录 (1).基于Ajax的前端实现 (2).Web服务器后端处理 一个完整的web服务器,不仅需要满足用户端对于图片.文档等资源的需求:还能够对于用户端的动态请求,返回指定程序生成的数据.支持动态请 ...

随机推荐

  1. (三)图数据库neo4j的安装配置

    (一)neo4j安装 neo4j有社区版本和企业版,社区版本是免费的,企业版本是收费的.在linux上安装如下步骤: 1.将下载的neo4j-enterprise-3.4.0-unix.tar.gz包 ...

  2. emacs 高亮

    用途:让某个单词高亮显示 1,安装 m-x 回车,输入list-packages 在列表中找到highlight-symbol后,鼠标点击它,再点击安装 2,在.emacs中配置 ;;高亮 (requ ...

  3. jdbc连接数据库,中文出现乱码的问题

    一.使用jdbc连接数据库,插入数据库时,数据里的数据显示乱码,为 " ??? " 两种解决方案: 1.修改服务端的mysql配置文件,编辑my.cnf文件,在[mysqld]下添 ...

  4. Node.js 事件循环机制

    Node.js 采用事件驱动和异步 I/O 的方式,实现了一个单线程.高并发的 JavaScript 运行时环境,而单线程就意味着同一时间只能做一件事,那么 Node.js 如何通过单线程来实现高并发 ...

  5. JavaScript 中的四舍五入

    在 JavaScript 中,对数值进行四舍五入操作的场景有以下几种: 向上取整:ceil 向下取整:floor 四舍五入:round 固定精度:toFixed 固定长度:toPrecision 取整 ...

  6. Unity项目开发过程中常见的问题,你遇到过吗?

    最近看到有朋友问一个unity游戏开发团队,需要掌握哪些知识之类的问题.事实上Unity引擎是一个很灵活的引擎,根据团队开发游戏类型的不同,对人员的要求也有差异,所以不能一概而论.但是,一些在Unit ...

  7. [AI开发]视频多目标跟踪高级版(离自动驾驶又‘近’了一点点)

    **本文恐怕不是完全的标题党** 视频多目标跟踪需要解决的关键点是前后两帧之间的Target Association,这是最难的环节(没有之一).第T帧检测到M个目标,第T+S(S>=1)帧检测 ...

  8. 解决ASP.NET Core MVC调试慢的问题

    最近在做的一个项目中,发现网页端同时发起了4个AJAX请求需要数秒才获取到响应,太慢了,当我把请求数降低为1个的时候,速度看起来就比较正常,增加到2个同时的请求后,速度就有些慢了,3个的话就明显慢了, ...

  9. Eureka源码探索(一)-客户端服务端的启动和负载均衡

    1. Eureka源码探索(一)-客户端服务端的启动和负载均衡 1.1. 服务端 1.1.1. 找起始点 目前唯一知道的,就是启动Eureka服务需要添加注解@EnableEurekaServer,但 ...

  10. DeviceUuidFactory【获取设备唯一标识码的UUID(加密)】【需要运行时权限的处理的配合】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 有时需要对用户设备进行标识,所以希望能够得到一个稳定可靠并且唯一的识别码.虽然Android系统中提供了这样设备识别码,但是由于An ...