httpserver 下载服务器demo

news2024/11/26 19:55:48

实现效果如下:

图片可以直接显示 

cpp h 这些可以直接显示 其他的 则是提示是否要下载

单线程 还有bug

代码如下  先放上来 

#include "httpserver.h"
#include "stdio.h"
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <dirent.h>


#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,"<html><head><title>%s</title></head><body><table>",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),
                "<tr><td><a href=\"%s/\">%s</a></td><td>%ld</td></tr>",name,name,st.st_size);
        }
        else
        {
            sprintf(buf+strlen(buf),
                "<tr><td><a href=\"%s\">%s</a></td><td>%ld</td></tr>",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,"</table></body></html>");

    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 <file_size)
        {
            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<nReady;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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1053185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

哈希表hash_table

一个人为什么要努力&#xff1f; 我见过最好的答案就是&#xff1a;因为我喜欢的东西都很贵&#xff0c;我想去的地方都很远&#xff0c;我爱的人超完美。文章目录 哈希表的引出unordered系列的关联式容器 底层结构哈希的概念 开放寻址法拉链法&#xff08;哈希桶&#xff09;拉…

【C++进阶】:C++11

C11 一.统一列表的初始化1.{}初始化2.initializer_list 二.声明1.decltype2.nullptr 三.右值引用和移动语义1.左值和右值1.转义语句2.完美转发 四.可变参数模板1.基本概念2.STL里emplace类接口 五.lambda表达式六.新的类功能 一.统一列表的初始化 1.{}初始化 在C98中&#xf…

CSS文本属性和Emmet语法

CSS文本属性 有预定的颜色值 red,green,blue 十六进制 #ff00000,#FF5500 ,#29D794 RGB代码 rgb(255,0,0)或rgb(100%,0%,0%) <head> <style>p {text-align: right;//让字体向右移动text-decoration: normal;}a {text-decoration: none;//去掉连接的下划线color: …

beego---ORM相关操作

Beego框架是go语言开发的web框架。 **那什么是框架呢&#xff1f;**就是别人写好的代码&#xff0c;我们可以直接使用&#xff01;这个代码是专门针对某一个开发方向定制的&#xff0c;例如&#xff1a;我们要做一个网站&#xff0c;利用 beego 框架就能非常快的完成网站的开发…

【随笔记】C++ condition_variable 陷阱

问题说明 通过 std::condition_variable 来实现超时等待&#xff0c;会受到系统时间变化的影响&#xff0c;系统时间倒退修改就会导致延后唤醒&#xff0c;系统时间提前将会导致提前被唤醒&#xff0c;返回结果仍为超时。 这种问题只有在系统时间发生变化的时候才会出现&…

MyBatisPlus(七)等值查询

等值查询 条件查询&#xff1a;使用 Wrapper 对象&#xff0c;传递查询条件。 QueryWrapper&#xff08;不要使用&#xff09; 代码 Testvoid eq() {QueryWrapper<User> wrapper new QueryWrapper<>();wrapper.eq("name", "张三");List<…

装饰器模式详解和实现(设计模式 二)

装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你动态地将对象添加到现有对象中&#xff0c;以提供额外的功能&#xff0c;同时又不影响其他对象。 实现示例 1.定义一个接口或抽象类&#xff0c;表示被装饰对象的公共接口 //抽…

CSS 滚动驱动动画 view-timeline-inset

view-timeline-inset 语法例子&#x1f330; 正 scroll-padding 为正正的 length正的 percentage 负 scroll-padding 为负负的 length负的 percentage 兼容性 view-timeline-inset 在使用 view() 时说过, 元素在滚动容器的可见性推动了 view progress timeline 的进展. 默认…

数据结构—快速排序(续)

引言&#xff1a;在上一篇中我们详细介绍了快速排序和改进&#xff0c;并给出了其中的一种实现方式-挖坑法 但其实快速排序有多种实现方式&#xff0c;这篇文章再来介绍其中的另外两种-左右指针法和前后指针法。有了上一篇挖坑法的启示&#xff0c;下面的两种实现会容易许多。 …

面试记录_

1&#xff1a;面试杉岩数据&#xff08;python开发&#xff09; 1.1.1 选择题 for(int i0;i<n;i){for(int j0;j<n;jji) } }O(n) * (O(0) O(n/1) O(n/2) O(n/3) ... O(n/n)) 在最坏情况下&#xff0c;内部循环的迭代次数为 n/1 n/2 n/3 ... n/n&#xff0c;这是…

电脑找不到vcruntime140_1.dll丢失的解决方法-一键修复教程

vcruntime140_1.dll是一个动态链接库文件&#xff0c;它是Microsoft Visual C Redistributable的一部分。这个库文件包含了一些运行时函数&#xff0c;用于支持各种软件程序的正常运行。当一个程序需要调用这些函数时&#xff0c;它会通过加载vcruntime140_1.dll文件来实现。因…

MySQL基础进阶

文章目录 MySQL基础进阶 约束 \color{red}{约束} 约束约束的概念和分类约束的概念约束的分类 非空约束概念语法 唯一约束概念语法 主键约束概念语法 数据库设计 \color{red}{数据库设计} 数据库设计软件的研发步骤数据库设计概念数据库设计的步骤表关系一对一一对多&#xff08…

Vue3父子组件数据传递

getCurrentInstance方法 Vue2中&#xff0c;可以通过this来获取当前组件实例&#xff1b; Vue3中&#xff0c;在setup中无法通过this获取组件实例&#xff0c;console.log(this)打印出来的值是undefined。 在Vue3中&#xff0c;getCurrentInstance()可以用来获取当前组件实例…

el-menu 导航栏学习(1)

最简单的导航栏学习跳转实例效果&#xff1a; &#xff08;1&#xff09;index.js路由配置&#xff1a; import Vue from vue import Router from vue-router import NavMenuDemo from /components/NavMenuDemo import test1 from /components/test1 import test2 from /c…

1200*B. Sorted Adjacent Differences(构造)

Problem - 1339B - Codeforces 解析&#xff1a; 题目要求每相邻两个值差的绝对值相等或递增。 先排序&#xff0c;可以想到我们先取两侧的数肯定相距最远&#xff0c;然后靠中心每次取两个数&#xff0c;这样符合题目要求。 直接遍历&#xff0c;先取的是答案靠后的数据&…

基于微信小程序的校园快递代取系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言用户微信小程序端的主要功能有&#xff1a;配送员微信小程序端的主要功能有&#xff1a;管理员的主要功能有&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获…

python爬取沈阳市所有肯德基餐厅位置信息

# 爬取沈阳所有肯德基餐厅位置信息 import requests import json import reurl http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?opkeyword headers {User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0…

Ipa Guard使用手册

使用手册 开始使用ipa guard代码混淆界面介绍文件混淆-界面介绍安装和登录Ipa Guard 相关教程 下载安装Ipa Guardipaguard注册和登录 下载安装Ipa Guard 可以前往ipaguard工具官网下载&#xff0c;工具是免费下载&#xff0c;免费体验使用的。下载地址是https://www.ipaguard.…

关于工作中爬取网站的一些思路记录

声明&#xff1a;只是因为工作中需要&#xff0c;且基本不会对别人的网站构成什么不好的影响&#xff0c;做个思路记录&#xff01;&#xff01;&#xff01; 尊重网站所有者、控制请求频率、遵守网站规则、尊重个人隐私 平常工作中难免会遇到需要爬取别人网站的需求&#xff0…

华为云云耀云服务器L实例评测 | 实例评测使用之硬件性能评测:华为云云耀云服务器下的硬件运行评测

华为云云耀云服务器L实例评测 &#xff5c; 实例评测使用之硬件性能评测&#xff1a;华为云云耀云服务器下的硬件运行评测 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为云云耀…