实现效果如下:
图片可以直接显示
cpp h 这些可以直接显示 其他的 则是提示是否要下载




单线程 还有bug
代码如下 先放上来
- #include "httpserver.h"
- #include "stdio.h"
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
-
- #define BURSIZE 1024
- int hex2dec(char c)
- {
- if ('0' <= c && c <= '9') {
- return c - '0';
- } else if ('a' <= c && c <= 'f') {
- return c - 'a' + 10;
- } else if ('A' <= c && c <= 'F') {
- return c - 'A' + 10;
- } else {
- return -1;
- }
- }
-
- char dec2hex(short int c)
- {
- if (0 <= c && c <= 9) {
- return c + '0';
- } else if (10 <= c && c <= 15) {
- return c + 'A' - 10;
- } else {
- return -1;
- }
- }
-
-
- /*
- * 编码一个url
- */
- void urlencode(char url[])
- {
- int i = 0;
- int len = strlen(url);
- int res_len = 0;
- char res[BURSIZE];
- for (i = 0; i < len; ++i) {
- char c = url[i];
- if (('0' <= c && c <= '9') ||
- ('a' <= c && c <= 'z') ||
- ('A' <= c && c <= 'Z') || c == '/' || c == '.') {
- res[res_len++] = c;
- } else {
- int j = (short int)c;
- if (j < 0)
- j += 256;
- int i1, i0;
- i1 = j / 16;
- i0 = j - i1 * 16;
- res[res_len++] = '%';
- res[res_len++] = dec2hex(i1);
- res[res_len++] = dec2hex(i0);
- }
- }
- res[res_len] = '\0';
- strcpy(url, res);
- }
-
- /*
- * 解码url
- */
- void urldecode(char url[])
- {
-
- int i = 0;
- int len = strlen(url);
- int res_len = 0;
- char res[BURSIZE];
- for (i = 0; i < len; ++i) {
- char c = url[i];
- if (c != '%') {
- res[res_len++] = c;
- } else {
- char c1 = url[++i];
- char c0 = url[++i];
- int num = 0;
- num = hex2dec(c1) * 16 + hex2dec(c0);
- res[res_len++] = num;
- }
- }
- res[res_len] = '\0';
- strcpy(url, res);
- }
-
-
- int CreateSocketFD()
- {
- int fd = 0;
- fd = socket(AF_INET,SOCK_STREAM,0);
- if(fd == -1)
- {
- perror("Scoket fd = -1");
- return 0;
- }
-
- int reuseport = 1;
- int ret = setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuseport,sizeof(reuseport));
- if(ret == -1)
- {
- perror("setsocketopt failed");
- return -1;
- }
-
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(8888);
- addr.sin_addr.s_addr = INADDR_ANY;
-
- ret = bind(fd,(struct sockaddr*)&addr,sizeof(addr));
- if(ret == -1)
- {
- perror("bind error");
- return -1;
- }
-
- ret = listen(fd,10);
-
- if(ret == -1)
- {
- perror("listen error ");
- return -1;
- }
-
- return fd;
- }
-
-
- int AcceptClients(int epoll_fd,int fd)
- {
- struct sockaddr addr;
- int cfd = accept(fd,NULL,NULL);
- if(cfd == -1)
- {
- perror("accept failed");
- }
-
-
- int flag = fcntl(cfd,F_GETFL);
- flag |= O_NONBLOCK;
-
- fcntl(cfd,F_SETFL,flag);
-
- struct epoll_event ev;
- ev.data.fd = cfd;
- ev.events = EPOLLIN|EPOLLET;
-
- int ret = epoll_ctl(epoll_fd,EPOLL_CTL_ADD,cfd,&ev);
- if(ret == -1)
- {
- perror("epoll ctl failed");
- return 0;
- }
-
- return 0;
- }
-
-
-
- const char *GetFileType(const char *filename)
- {
- const char *dot = strrchr(filename,'.');
- if(dot == NULL)
- {
- return "text/plain; charset=utf-8";
- }
- if(strcmp(dot,".jpg") == 0 ||strcmp(dot,".jpeg") == 0)
- {
- return "image/jpg";
- }
- if(strcmp(dot,".html") == 0 ||strcmp(dot,".htm") == 0)
- {
- return "text/html; charset=utf-8";
- }
- if(strcmp(dot,".png") == 0)
- {
- return "image/png";
- }
- if(strcmp(dot,".bmp") == 0)
- {
- return "image/bmp";
- }
- if(strcmp(dot,".gif") == 0)
- {
- return "image/gif";
- }
- if(strcmp(dot,".css") == 0)
- {
- return "text/css";
- }
- if(strcmp(dot,".mp3") == 0)
- {
- return "audio/mpeg";
- }
-
- return "text/plain; charset=utf-8";
- }
-
- int SendHead(int cfd,int status ,const char *desc,const char *type,int size)
- {
- char buf[4096] = {0};
- sprintf(buf,"http/1.1 %d %s\r\n",status,desc);
- sprintf(buf+strlen(buf),"content-type: %s\r\n",type);
- sprintf(buf+strlen(buf),"content-length: %d\r\n\r\n",size);
-
-
- printf("SendHead buf[%s]\n",buf);
-
- send(cfd,buf,strlen(buf),0);
- return 0;
- }
-
-
- int SendDir(const char *dirname,int cfd)
- {
- char buf[4096] = {0};
-
- sprintf(buf,"
%s ",dirname);-
- printf("SendDir dirname=[%s]\n",dirname);
- struct dirent **namelist;
- int count = scandir(dirname,&namelist,NULL,alphasort);
- printf("SendDir count=[%d]\n",count);
- for(int i = 0;i< count;i++)
- {
- char *name = namelist[i]->d_name;
- struct stat st;
- char sub_path[1024]={0};
- sprintf(sub_path,"%s/%s",dirname,name);
- stat(sub_path,&st);
- if(S_ISDIR(st.st_mode))
- {
- sprintf(buf+strlen(buf),
- "
%s %ld ",name,name,st.st_size); - }
- else
- {
- sprintf(buf+strlen(buf),
- "
%s %ld ",name,name,st.st_size); - }
-
- printf("cfd:%d Sendbuf[%s]\n",cfd,buf);
- send(cfd,buf,strlen(buf),0);
- memset(buf,0,sizeof(buf));
- free(namelist[i]);
- }
-
- sprintf(buf,"
"); -
- printf("cfd:%d Sendbuf[%s]\n",cfd,buf);
-
- send(cfd,buf,strlen(buf),0);
- free(namelist);
-
- return 0;
- }
-
- int SendFile(const char* filename,int cfd)
- {
- int fd = open(filename,O_RDONLY);
- if(fd >0)
- {
-
- #if 0
- while(1)
- {
- char buf[1024];
- int len = read(fd,buf,sizeof buf);
- if(len >0)
- {
- send(cfd,buf,len,0);
- usleep(10);
- }
- else if(len == 0)
- {
- printf("Read file end\n");
- break;
- }
- else
- {
- perror("read error");
- }
- }
- #else
- off_t offset = 0;
- int file_size = lseek(fd,0,SEEK_END);
- lseek(fd,0,SEEK_SET);
-
- while(offset
- {
- int send_len = sendfile(cfd,fd,&offset,file_size-offset);
-
- if(send_len == -1)
- {
- if(errno == EAGAIN)
- {
- //perror("sendfile no data send");
- }
- else
- {
- perror("sendfile ret -1");
- }
-
- }
- else
- {
- printf("Send len:%d\n",send_len);
- }
- }
-
- #endif
- }
- else
- {
- perror("open file failed");
- }
- close(fd);
- return 0;
- }
-
- int ParseReqLine(const char *line,int cfd)
- {
- char method[12];
- char path[1024];
-
- printf("ParseReqLine=[%s]\n",line);
-
- int ret = sscanf(line,"%[^ ] %[^ ]",method,path);
- printf("sscanf ret = %d\n",ret);
- printf("method=[%s],path=[%s]\n",method,path);
-
- urldecode(path);
- printf("afterdecode path=[%s]\n",path);
- if(ret ==2 )
- {
-
- }
- else
- {
- printf("Reqest line parse failed\n");
- return -1;
- }
-
- if(strcasecmp(method,"get") == 0)
- {
-
- }
- else if(strcasecmp(method,"post")==0)
- {
-
- }
- else
- {
- return -1;
- }
-
- char *file = NULL;
- if(strcmp(path,"/") == 0)
- {
- file = "./";
- }
- else
- {
- file = path+1;
- }
-
- struct stat st;
-
- ret = stat(file,&st);
- if(ret == -1)
- {
- printf("file doest not exist\n");
- SendHead(cfd,404,"Not found",GetFileType(".html"),-1);
- SendFile("404.html",cfd);
- return -1;
- }
-
- if(S_ISDIR(st.st_mode))
- {
- printf("Directory\n");
- SendHead(cfd,200,"OK",GetFileType(".html"),-1);
- SendDir(file,cfd);
- }
- else
- {
- printf("File\n");
- SendHead(cfd,200,"OK",GetFileType(file),st.st_size);
- SendFile(file,cfd);
- }
-
-
- return 0;
- }
-
- int Request(int epoll_fd,int cfd)
- {
- char buffer[4096] = {0};
- char temp_buf[1024] = {0};
- int read_len = 0;
- int total = 0;
- while((read_len = recv(cfd,temp_buf,sizeof(temp_buf),0))>0)
- {
- if(total+read_len <sizeof(buffer))
- {
- memcpy(buffer+total,temp_buf,read_len);
- total+=read_len;
- }
-
- }
-
- if(read_len == -1 && errno == EAGAIN)
- {
- //读取数据结束
- char *p = strstr(buffer,"\r\n");
- if(p)
- {
- int len = p - buffer;
- buffer[len] = 0;
- ParseReqLine(buffer,cfd);
- }
-
- }
- else if(read_len == 0)
- {
- //Client close socket
- epoll_ctl(epoll_fd,EPOLL_CTL_DEL,cfd,NULL);
- close(cfd);
- }
- else
- {
- perror("recv error");
- }
- return 0;
- }
-
-
- int EPOLL_Run(int server_fd)
- {
- int epoll_fd = epoll_create(10);
- if(epoll_fd == -1)
- {
- perror("epoll_create failed");
- return 0;
- }
-
- struct epoll_event ev;
- ev.data.fd = server_fd;
- ev.events = EPOLLIN;
- int ret = epoll_ctl(epoll_fd,EPOLL_CTL_ADD,server_fd,&ev);
- if(ret == -1)
- {
- perror("epoll_ctl failed");
- return 0;
- }
-
- struct epoll_event events[512];
-
- while(true)
- {
- int nReady = epoll_wait(epoll_fd,events,512,-1);
-
- for(int i = 0;i
- {
- int fd = events[i].data.fd;
- if(fd == server_fd)
- {
- AcceptClients(epoll_fd,fd);
- }
- else
- {
- if(events[i].events &EPOLLOUT)
- {
- //g_writeable = true;
- printf("客户端可以写数据了");
- }
- if(events[i].events &EPOLLIN)
- {
- Request(epoll_fd,fd);
- }
-
- }
- }
- }
-
- return epoll_fd;
- }
- int main()
- {
- printf("Hello world\n");
-
- char work_dir[] = "/home/develop/httpserver";
- //chdir(work_dir);
-
- int server_fd = CreateSocketFD();
-
- if(server_fd <=0)
- {
- return 0;
- }
-
- EPOLL_Run(server_fd);
-
- close(server_fd);
- return 0;
- }
以上 如果遇到大文件 比如mp3 文件的话 就没办法 预览 试听 下载大文件也有问题
跟踪发现是SendFile 那里有问题 会返回-1
根据网上的例子 改了一个 基于libevent版本的 不会存在这个问题
- #include "sushi.h"
- #include "stdio.h"
-
-
-
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
-
- #include
- #include
- #include
- #include
-
-
-
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #include
-
-
-
-
-
- #include
- #include
- #include
- #include "event2/http.h"
- #include "event2/event.h"
- #include "event2/buffer.h"
- #include "event2/bufferevent.h"
- #include "event2/bufferevent_compat.h"
- #include "event2/http_struct.h"
- #include "event2/http_compat.h"
- #include "event2/util.h"
- #include "event2/listener.h"
- #include "event2/thread.h"
-
-
- #define MAX_EVENTS 100
- #define RECVBUFSIZ 20
-
- bool g_run_flag = true;
-
-
- void sig_handler(int signo)
- {
- g_run_flag = false;
- printf("\033[0;31mprogram exit by user cmd !!!!\033[0;39m\n");
- }
-
-
-
- #define BURSIZE 1024
- int hex2dec(char c)
- {
- if ('0' <= c && c <= '9') {
- return c - '0';
- } else if ('a' <= c && c <= 'f') {
- return c - 'a' + 10;
- } else if ('A' <= c && c <= 'F') {
- return c - 'A' + 10;
- } else {
- return -1;
- }
- }
-
- char dec2hex(short int c)
- {
- if (0 <= c && c <= 9) {
- return c + '0';
- } else if (10 <= c && c <= 15) {
- return c + 'A' - 10;
- } else {
- return -1;
- }
- }
-
-
- /*
- * 编码一个url
- */
- void urlencode(char url[])
- {
- int i = 0;
- int len = strlen(url);
- int res_len = 0;
- char res[BURSIZE];
- for (i = 0; i < len; ++i) {
- char c = url[i];
- if (('0' <= c && c <= '9') ||
- ('a' <= c && c <= 'z') ||
- ('A' <= c && c <= 'Z') || c == '/' || c == '.') {
- res[res_len++] = c;
- } else {
- int j = (short int)c;
- if (j < 0)
- j += 256;
- int i1, i0;
- i1 = j / 16;
- i0 = j - i1 * 16;
- res[res_len++] = '%';
- res[res_len++] = dec2hex(i1);
- res[res_len++] = dec2hex(i0);
- }
- }
- res[res_len] = '\0';
- strcpy(url, res);
- }
-
- /*
- * 解码url
- */
- void urldecode(char url[])
- {
-
- int i = 0;
- int len = strlen(url);
- int res_len = 0;
- char res[BURSIZE];
- for (i = 0; i < len; ++i) {
- char c = url[i];
- if (c != '%') {
- res[res_len++] = c;
- } else {
- char c1 = url[++i];
- char c0 = url[++i];
- int num = 0;
- num = hex2dec(c1) * 16 + hex2dec(c0);
- res[res_len++] = num;
- }
- }
- res[res_len] = '\0';
- strcpy(url, res);
- }
-
- const char *GetFileType(const char *filename)
- {
- const char *dot = strrchr(filename,'.');
- if(dot == NULL)
- {
- return "text/plain; charset=utf-8";
- }
- if(strcmp(dot,".jpg") == 0 ||strcmp(dot,".jpeg") == 0)
- {
- return "image/jpg";
- }
- if(strcmp(dot,".html") == 0 ||strcmp(dot,".htm") == 0)
- {
- return "text/html; charset=utf-8";
- }
- if(strcmp(dot,".png") == 0)
- {
- return "image/png";
- }
- if(strcmp(dot,".bmp") == 0)
- {
- return "image/bmp";
- }
- if(strcmp(dot,".gif") == 0)
- {
- return "image/gif";
- }
- if(strcmp(dot,".css") == 0)
- {
- return "text/css";
- }
- if(strcmp(dot,".mp3") == 0)
- {
- return "audio/mpeg";
- }
-
- return "text/plain; charset=utf-8";
- }
-
-
- int SendHead(struct bufferevent *event,int status ,const char *desc,const char *type,int size)
- {
- char buf[4096] = {0};
- sprintf(buf,"http/1.1 %d %s\r\n",status,desc);
- sprintf(buf+strlen(buf),"content-type: %s\r\n",type);
- sprintf(buf+strlen(buf),"content-length: %d\r\n\r\n",size);
-
-
- printf("SendHead buf[%s]\n",buf);
-
- //send(cfd,buf,strlen(buf),0);
- bufferevent_write(event,buf,strlen(buf));
- return 0;
- }
-
-
- int SendDir(struct bufferevent *event,const char *dirname)
- {
- char buf[4096] = {0};
-
- sprintf(buf,"
%s ",dirname);-
- printf("SendDir dirname=[%s]\n",dirname);
- struct dirent **namelist;
- int count = scandir(dirname,&namelist,NULL,alphasort);
- printf("SendDir count=[%d]\n",count);
- for(int i = 0;i< count;i++)
- {
- char *name = namelist[i]->d_name;
- struct stat st;
- char sub_path[1024]={0};
- sprintf(sub_path,"%s/%s",dirname,name);
- stat(sub_path,&st);
- if(S_ISDIR(st.st_mode))
- {
- sprintf(buf+strlen(buf),
- "
%s %ld ",name,name,st.st_size); - }
- else
- {
- sprintf(buf+strlen(buf),
- "
%s %ld ",name,name,st.st_size); - }
-
- //printf("cfd:%d Sendbuf[%s]\n",cfd,buf);
- //send(cfd,buf,strlen(buf),0);
- bufferevent_write(event,buf,strlen(buf));
- memset(buf,0,sizeof(buf));
- free(namelist[i]);
- }
-
- sprintf(buf,"
"); -
- //printf("cfd:%d Sendbuf[%s]\n",cfd,buf);
-
- //send(cfd,buf,strlen(buf),0);
- bufferevent_write(event,buf,strlen(buf));
- free(namelist);
-
- return 0;
- }
-
- int SendFile(struct bufferevent *event,const char* filename)
- {
- int fd = open(filename,O_RDONLY);
- if(fd >0)
- {
-
- #if 1
- while(1)
- {
- char buf[1024];
- int len = read(fd,buf,sizeof buf);
- if(len >0)
- {
- //send(cfd,buf,len,0);
- bufferevent_write(event,buf,len);
- usleep(10);
- }
- else if(len == 0)
- {
- printf("Read file end\n");
- break;
- }
- else
- {
- perror("read error");
- }
- }
- #else
- off_t offset = 0;
- int file_size = lseek(fd,0,SEEK_END);
- lseek(fd,0,SEEK_SET);
-
- while(offset
- {
- int send_len = sendfile(cfd,fd,&offset,file_size-offset);
-
- if(send_len == -1)
- {
- if(errno == EAGAIN)
- {
- //perror("sendfile no data send");
- }
- else
- {
- perror("sendfile ret -1");
- }
-
- }
- else
- {
- printf("Send len:%d\n",send_len);
- }
- }
-
- #endif
- }
- else
- {
- perror("open file failed");
- }
- close(fd);
- return 0;
- }
-
-
-
-
- int http_request(struct bufferevent *event,char *path)
- {
- char *file = NULL;
-
- if(strcmp(path,"/") == 0)
- {
- file = "./";
- }
- else
- {
- file = path+1;
- }
-
- struct stat st;
-
- int ret = stat(file,&st);
- if(ret == -1)
- {
- printf("file doest not exist\n");
- SendHead(event,404,"Not found",GetFileType(".html"),-1);
- SendFile(event,"404.html");
- return -1;
- }
-
- if(S_ISDIR(st.st_mode))
- {
- printf("Directory\n");
- SendHead(event,200,"OK",GetFileType(".html"),-1);
- SendDir(event,file);
- }
- else
- {
- printf("File\n");
- SendHead(event,200,"OK",GetFileType(file),st.st_size);
- SendFile(event,file);
- }
-
- return 0;
- }
-
- void read_cb(struct bufferevent *event,void *arg)
- {
- char buf[256] = {0};
- char method[10]= {0},path[256]={0},protocol[10]={0};
-
- int ret = bufferevent_read(event,buf,sizeof(buf));
- if(ret >0)
- {
- sscanf(buf,"%[^ ] %[^ ] %[^ \r\n]",method,path,protocol);
- if(strcasecmp(method,"get") == 0)
- {
- char bufline[256] = {0};
- write(STDOUT_FILENO,buf,ret);
- while((ret = bufferevent_read(event,bufline,sizeof(bufline)))>0)
- {
- write(STDOUT_FILENO,bufline,ret);
- }
- http_request(event,path);
- }
- }
- }
-
-
- void bevent_cb(struct bufferevent *event,short what,void *arg)
- {
- if(what & BEV_EVENT_EOF)
- {
- printf("client closeed\n");
- bufferevent_free(event);
- }
- else if(what & BEV_EVENT_ERROR)
- {
- printf("client error\n");
- bufferevent_free(event);
- }
- else if(what & BEV_EVENT_CONNECTED)
- {
- printf("new client connected\n");
- }
- }
-
- void listener_cb(struct evconnlistener *listener,evutil_socket_t fd,struct sockaddr *addr,int socklen,void *arg)
- {
- struct event_base *base = (struct event_base*)arg;
- struct bufferevent *event= bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
- bufferevent_setcb(event,read_cb,NULL,bevent_cb,base);
- bufferevent_enable(event,EV_READ|EV_WRITE);
- }
-
-
- int main (int argc ,char*argv[])
- {
-
-
-
- signal(SIGINT, sig_handler);
- signal(SIGTERM, sig_handler);
- signal(SIGKILL, sig_handler);//Program can not recieve SIGKILL(9) signal so.... this cmd does not make any sense
-
- // Ignore broken pipes
- signal(SIGPIPE, SIG_IGN);
-
-
- char work_dir[256]={0};
- strcpy(work_dir,getenv("PWD"));
- printf("dir:%s\n",work_dir);
- chdir(work_dir);
-
- struct event_base *base = event_base_new();
- struct sockaddr_in server;
- server.sin_family = AF_INET;
- server.sin_port = htons(9999);
- server.sin_addr.s_addr = htonl(INADDR_ANY);
- struct evconnlistener *listener = evconnlistener_new_bind(base,listener_cb,base,
- LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE_PORT,-1,
- (struct sockaddr *)&server,sizeof(server));
-
-
- event_base_dispatch(base);
- event_base_free(base);
-
- evconnlistener_free(listener);
-
-
- printf("Exit normally\n");
- return 0;
- }
-
相关阅读:
Linux安装与卸载Jenkins
Java版正则表达式实现
C语言内功修炼--指针详讲(进阶)
Websocket升级版
解读云视商系统开发等主流9大电商APP商业模式
学习笔记-关于过滤\<\?php标签这件事
【.NET8】访问私有成员新姿势UnsafeAccessor(上)
深入理解Linux进程管理与优化:原理、调度和资源控制详解
GO学习之 远程过程调用(RPC)
动画详解常用排序算法(1)
-
原文地址:https://blog.csdn.net/baoecit/article/details/133445242