自己写的功能简单的 http server 文件下载服务器 http服务器

news2025/6/7 21:05:25

最近在项目中遇到过 通过ssh登录到某台机器A ,然后 又从A机器上ssh到机器B  而B机器是没有外网功能,这个时候如果想从B机器上传文件到A机器上就很不好办了  由于B机器没有外网 很多工具软件都没有  原来是是用python 起的http服务器 但是B机器没有安装python

于是就参照之前的项目经历写了一个简单的http server服务端 ,编译之后放在B机器上

然后在A机器上就可以通过wget命令 把文件下载下来了 

运行环境ubuntu 18.04  依赖于libevent库 

运行方式:

下载方式:

 程序同级目录需要有个download目录 程序里面写死了 是这个download目录 把需要下载的文件放到download目录即可

临时用可以了 解决了不能从B机器上下载文件到A机器上的问题 

下面直接贴源码:

#include"QMCY_HttpServer.h"


#include <future>



#define HTTP_PORT	8081
	//#define HTTP_IP	"0.0.0.0"
	
#define BUF_MAX 1024*16
#define CHANNEL_LIST_SIZE	1024*20
	
	char g_get_buf[CHANNEL_LIST_SIZE] = {0};
	char g_log_file_name[256]="123";

QMCY_OSD* g_pHandle =  NULL;




void QMCY_SendResponse(HTTP_REQ *req,const char* content)
{
	struct evbuffer *retbuff = NULL;
	retbuff = evbuffer_new();	
	if(retbuff == NULL)
	{
		printf("ret buff is NULL \n");
		//QMCY_LOG(HT_LOG_WARN,"QMCY_SendResponse get memory failed\n");
		return;
	}	
	evbuffer_add_printf(retbuff,content);
	evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
	evbuffer_free(retbuff);	
}



void QMCY_PostHandler(HTTP_REQ *req,void *arg)
{
	char *buf = NULL;
	int valid_channels = 0;
	QMCY_OSD *pHandle =(QMCY_OSD*)arg;

	size_t post_size = 0;

	MSG_INFO msg;
	memset(&msg, 0, sizeof(msg));
	
	post_size = evbuffer_get_length(req->input_buffer);
	if (post_size == 0)
	{
		printf("QMCY post msg is empty!\n");
		return;
	}

	buf = (char*)malloc(post_size+1);
	if(buf == NULL)
	{
		return;
	}
	memset(buf,0,post_size+1);
	const char *uri = evhttp_request_get_uri(req);	

	size_t copy_len = post_size > BUF_MAX ? BUF_MAX : post_size;
	memcpy(buf, evbuffer_pullup(req->input_buffer,-1), copy_len);


	evhttp_add_header(evhttp_request_get_output_headers(req),
			"Content-Type", "application/json");


	QMCY_SendResponse(req,"{\"msg\":\"Success\", \"code\":200}");

	if(strcmp(uri,POST_URI_SET_LED) == 0)
	{

	}
	else if(strcmp(uri,POST_URI_UPDATE_LED) == 0)
	{


		
	}	
	
	else if(strcmp(uri,POST_URI_STOP) == 0)
	{

	}

	else
	{

		printf("Post is:[%s]\n",buf);
	
		//QMCY_LOG(HT_LOG_WARN,"Undefined post method:%s\n",uri);
	}

	free(buf);

}








void QMCY_GetHandler(HTTP_REQ *req,void *arg)
{
	char *buf = g_get_buf;

	QMCY_OSD *pHandle = (QMCY_OSD *)arg;

	char file_buf[1024] = { 0 };

	if(pHandle == NULL)
	{
		return;
	}
	
	if(!req )
	{
		return ;
	}


	memset(buf,0,CHANNEL_LIST_SIZE);
	
	const char *uri = evhttp_request_get_uri(req);	

	//evhttp_set_default_content_type

	evhttp_add_header(evhttp_request_get_output_headers(req),
			"Content-Type", "application/json");


	if(strncmp(uri,"/download",strlen("/download")) == 0)
	{
		string file_name = ".";
		file_name.append(uri);

		if(file_name == "./download" || file_name == "./download/")
		{
			printf("file does not exist\n");
			evhttp_send_reply(req, HTTP_NOTFOUND, "File not found", 0);//返回未找到
			return;
		}

		long filesize = 0;

		printf("Request file is[%s]\n",file_name.c_str());

		//log_print(HT_LOG_INFO,"%s Request file is[%s]\n",__FUNCTION__,file_name.c_str());					

		//读取html文件返回正文
		FILE *fp = fopen(file_name.c_str(), "rb");
		if (!fp){
			printf("file does not exist\n");
			evhttp_send_reply(req, HTTP_NOTFOUND, "File not found", 0);//返回未找到
			//这里可以自定义未找到页面
			return;
		}

		fseek(fp, 0, SEEK_END);
		filesize = ftell(fp);
		fseek(fp,0,SEEK_SET);

		time_t timep;
		time(&timep);
		char s[50];
		sprintf(s, ctime(&timep));
  		std::string strDate = std::string(s, s + (strlen(s) - 1));
		char FileSize[10] = {0};

		snprintf(FileSize, sizeof(FileSize), "%d", filesize);

		evhttp_add_header(evhttp_request_get_output_headers(req), "Server", "QMCY");
		evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "application/octet-stream; charset=utf-8");
		evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Disposition", file_name.c_str());
		evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Length", FileSize);
		evhttp_add_header(evhttp_request_get_output_headers(req), "Date", strDate.c_str());
		evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close");

		evbuffer *outbuf = evhttp_request_get_output_buffer(req); //返回的body
		while (true){
			int len = fread(file_buf, 1, sizeof(file_buf), fp); //不断读取,解决文件过大一次性读不完的问题
			if (len <= 0)break;
			evbuffer_add(outbuf, file_buf, len);
		}
		
		fclose(fp);
		printf("Read complete send to client\n");

		//log_print(HT_LOG_INFO,"%s Read complete send to client [%s]\n",__FUNCTION__,file_name.c_str());					

		evhttp_send_reply(req, HTTP_OK, "Client", outbuf);

		QMCY_SendResponse(req,"Download finished!!!");
		return;
	}
	else if(strcmp(uri,GET_URI_LOGNAME) == 0)
	{

	}	
	else if((strcmp(uri,GET_URI_CHANNEL_LIST) == 0))
	{
	}
	else if((strcmp(uri,GET_URI_TEST) == 0))
	{
		//QMCY_ParseAuthentication(NULL,pHandle);
	}	
	else
	{
		sprintf(buf,
			"{\r\n "
			"%s:%s" 		
			"\r\n}","Undefined command!!!",uri);

		//QMCY_LOG(HT_LOG_WARN,"Undefined GET method:%s\n",uri);

	}

	QMCY_SendResponse(req,buf);


	
}



void QMCY_HttpHandler(HTTP_REQ *req,void *arg)
{
	int method= 0;

	if(req == NULL)
	{
		return;
	}
	method = evhttp_request_get_command(req);
	
	if(method == EVHTTP_REQ_GET)
	{
		QMCY_GetHandler(req,arg);
	}
	if(method == EVHTTP_REQ_POST)
	{
		QMCY_PostHandler(req,arg);
	}

	return;

}


void QMCY_StopHttp()
{
	event_loopbreak();
}



void * QMCY_StartHttp(void *args)
{
	struct evhttp *http_server = NULL;
	short http_port = HTTP_PORT;
	const char *http_addr = HTTP_IP;

	QMCY_OSD *pHandle =reinterpret_cast<QMCY_OSD *>(args);
	
	http_port = pHandle->local_port;

#if defined(_WIN32) || defined(_WIN64)
	evthread_use_windows_threads();
#else
	evthread_use_pthreads();
#endif
	
	event_init();

	http_server = evhttp_start(http_addr,http_port);
	if(http_server == NULL)
	{
		printf("Http server start failed.\n");
		//QMCY_LOG(HT_LOG_FATAL,"Http server start failed\n");

		QMCY_Stop(pHandle);
		return NULL;
	}
	else
	{
		printf("Http server start at %s:%d.\n",pHandle->local_ip,pHandle->local_port);
		//QMCY_LOG(HT_LOG_INFO,"Http server start at %s:%d.\n",pHandle->device_ip,pHandle->device_port);
	}
	
	evhttp_set_timeout(http_server,5);
	//evhttp_set_cb(http_server, "/qmcy/upload", HttpUpFile, NULL);
	evhttp_set_gencb(http_server,QMCY_HttpHandler, args);

	event_dispatch();
	evhttp_free(http_server);
	printf("\n Http server exit.\n");
	//QMCY_LOG(HT_LOG_INFO,"Http server exit\n"); 
	return NULL;	
}







void handler(int signum)
{
    if(signum == SIGIO)
        printf("SIGIO   signal: %d\n", signum);
    else if(signum == SIGPIPE)
        printf("SIGPIPE   signal: %d\n", signum);
    else
	{
		QMCY_Stop(g_pHandle);
		printf("error\n");
	}
}


int QMCY_Start(QMCY_OSD *pHandle)
{

	pHandle->http_thread = std::thread(QMCY_StartHttp, pHandle);
	pHandle->run_flag.store(true);

	printf("QMCY OSD system successfully started\n");
	
	while(pHandle->run_flag.load())
	{
		sleep(1);
	}
 	cout << __FUNCTION__ << " exit" << endl;
	return 1;
	
}



void QMCY_Stop(QMCY_OSD *pHandle)
{
	pHandle->run_flag.store(false);

	
	QMCY_StopHttp();
	
	pHandle->http_thread.join();



}



int main(int argc,char *argv[])
{
	int ret = 0;
	int port = 8000;

	
	QMCY_OSD  handle ={0};

	g_pHandle = &handle;


	if(argc == 2)
	{
		port = atoi(argv[1]);
	}

	handle.local_port = port;


	signal(SIGPIPE, SIG_IGN);

	
	QMCY_Start(&handle);

	QMCY_Stop(&handle);

	printf("QMCY ------------------------> Exit normally \n");		
}

由于这个是从其他项目里面摘出来的 所以有很多额外的代码痕迹 略过即可 

更新了下 之前 必须程序同级目录有download目录才可以 现在去掉了这个限制

直接是程序运行当前目录即可:

运行如下:

 下载方式:

程序当前目录详情:

 

 

这样就和python的http方式一样了

python -m SimpleHTTPServer 8000

代码其实更简单 只需要把download那里注释掉就可以了

如下:

 

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

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

相关文章

Black Basta 勒索软件利用 QakBot 进行分发

自 2022 年 4 月投入运营以来&#xff0c;Black Basta 对全球近 50 家组织发起了攻击。攻击者使用了“双重勒索”策略&#xff0c;如果受害者不交付赎金就会被公开数据。 勒索团伙会不断改进攻击方式&#xff0c;最近研究人员发现 Black Basta 与银行木马 QakBot 勾结在一起&a…

nginx+uwsgi部署django项目

1. python3.9环境安装 安装依赖 yum install zlib zlib-devel libffi-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make wget下载源码 官网地址 wget https://www.python.org/ftp/python/3.9.6/Python-3.9.6.tar.xz解压 &…

maven的下载与安装

前言 本篇文章是基于win11系统下载安装Maven的教程。 一、 Maven介绍 1. 什么是Maven&#xff1f; Maven是基于项目对象模型(POM project object model)&#xff0c;可以通过一小段描述信息&#xff08;配置&#xff09;来管理项目的构建&#xff0c;报告和文档的软件项目管…

【FreeRTOS】详细讲解FreeRTOS中任务管理并通过示例讲述其用法

任务状态 在FreeRTOS中一个任务经创建后会有多个状态&#xff0c;通常可分为以下几种状态&#xff1a; 就绪态&#xff1a;新创建的任务一般处于就绪态。处于就绪态的任务表明其已经存在于就绪列表中&#xff0c;其已经具备所有的任务执行需要条件&#xff0c;只等待调度器调度…

社科院杜兰大学金融管理硕士项目——美丽的风景,在你前行的路上

一个人的强大源于内心的坚定&#xff0c;内心强大的人&#xff0c;是平和的、自信的、乐观的。在工作中也是奋发图强、积极向上的&#xff0c;就像选择来社科院与杜兰大学金融管理硕士充电&#xff0c;为职场发展注入能量&#xff0c;为未来发展奠定基础。近些年来&#xff0c;…

Centos7离线安装MySQL

使用tar.gz文件安装MySQL 1、下载MySQL离线包 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 根据需要下载对应版本tar.gz文件&#xff0c;下载完成后上传到服务器 2、解压tar.gz文件 tar -zxvf mysql-5.7.37-linux-glibc2.12-x86_64.tar.gz等待解…

【计算机网络】TCP/UDP协议

传输层协议 负责数据能够从发送端传输接收端,这篇文章主要介绍TCP和UDP协议 UDP协议 学习UDP协议需要掌握&#xff0c;UDP协议如何做到封装和解包的&#xff0c;如何做到向上交付的&#xff08;分用问题&#xff09; UDP协议格式 封装&#xff1a;添加定长报头 解包&…

用Python掌握QQ群聊天记录数据分析

当你打开QQ群时,你是否想过如何用Python提取里面的数据呢?随着社交媒体的兴起,QQ群成为了人们交流的重要平台,而提取这些数据可以帮助我们了解用户喜好和行为。那么,如何使用Python提取QQ群数据呢? 这里做了一套脚本用于提取QQ群的消息并进行一些简单的处理。 其中包括…

IB、AP、A-LEVEL,哪种最适合自己呢?

刚开始了解新加坡留学的家长和学生&#xff0c;一定看到这些就觉得头大吧。当下国际学校里的课程可以说五花八门&#xff0c;在选择之前一定要弄清楚这些名词背后的含义…… IB是什么 IB&#xff08;International Baccalaureate&#xff09;全称为国际预科证书课程&#xff0c…

Linux下rabbitmq的集群搭建

1 修改 3 台机器的主机名称 在三台服务器分别执行 hostnamectl set-hostname master hostnamectl set-hostname node01 hostnamectl set-hostname node022 配置各个节点的 hosts 文件 vim /etc/hosts 192.168.5.6 master 192.168.5.7 node01 192.168.5.8 node023 确保各个节…

【工具】苏格拉底式诘问法解决工作问题

目录一、什么是苏格拉底式诘问法二、苏格拉底式诘问法的细分三、在实际工作中运用苏格拉底式诘问法解决问题一、什么是苏格拉底式诘问法 苏格拉底式诘问法&#xff08;Socratic Elenchus&#xff09;是苏格拉底式提问的一种&#xff0c;也叫做"诘问法"。它是由古希腊…

OpenCV-PyQT项目实战(2)QtDesigner 和 PyUIC 快速入门

欢迎关注『OpenCV-PyQT项目实战 Youcans』系列&#xff0c;持续更新中 OpenCV-PyQT项目实战&#xff08;1&#xff09;安装与环境配置 OpenCV-PyQT项目实战&#xff08;2&#xff09;QtDesigner 和 PyUIC 快速入门 OpenCV-PyQT项目实战&#xff08;3&#xff09;信号与槽机制 …

【Java】final的关键字和final的四种用法

final定义 final翻译成中文的意思是 “最终” &#xff0c; 它是java当中的一个关键字&#xff0c;使用final修饰的对象不允许修改或替换其原始值或定义。 假如当final修饰一个类的时候&#xff0c;是不能被其他类继承的。 final的四种用法 修饰类修饰方法修饰变量修饰参数 1.…

Oracle 里的优化器

对于关系型数据库而言&#xff0c;优化器是最核心的部分。主要是因为优化器负责解析SQL。而大家都是通过SQL来访问存储在数据库中的数据。故此&#xff0c;优化器的好坏直接决定该关系型数据库的强弱。 同时&#xff0c;想要做好SQL优化&#xff0c;就必须深入了解优化器。这是…

源表的基础知识

浅谈“源表”的定义、功能及应用 源表与传统电源的区别 源表速度更快&#xff1b; 源表电流、电压分辨率更高&#xff1b; 源表是四象限&#xff0c;可以正电压&#xff08;源表提供给外部&#xff09;负电流&#xff08;外部灌入源表&#xff09;或者负电压、正电流。 传统电…

3.组件的基本用法

目录 1 创建组件 1.1 用函数创建组件 1.2 使用类创建组件 2 项目上组件的使用方式 3 事件处理 3.1 事件绑定 3.1.1 类组件绑定事件 3.1.2 函数组件绑定事件 3.2 事件对象 4 组件状态 4.1 初始化状态 4.2 获取状态 4.3 设置状态 4.3.1 箭头函数 4.…

win10下Elasticsearch安装配置完整教程

一、在安装Elasticsearch引擎之前&#xff0c;必须安装ES需要的软件环境&#xff0c;安装Java JDK和配置JAVA_HOME环境变量 二.安装ElasticSearch服务&#xff0c;下载和安装es包 https://www.elastic.co/downloads/past-releases Elasticsearch 8.6.1 | Elastic 安装成功之…

数据结构 第五章 数组和广义表

还是会想你&#xff1a;点击收听 1 基本知识点 1、数组可以看作是下标和值的偶对的集合(具有相同类型的数据元素) 注意&#xff1a;数组是同类型值的集合&#xff1f;**错误**2、数组的存储方式&#xff1a;以行为主序(一行存储完成之后继续存储下一行)、以列为主序(一列存储…

【C++修行之路】C++入门之深剖变量

&#x1f37f;本文主题&#xff1a;C语法中的变量 &#x1f388;更多内容&#xff1a;C较C的改进 &#x1f495;我的主页&#xff1a;蓝色学者 文章目录前言概念什么是变量变量名变量类型为什么要有不同数据类型各自数据类型的本质结语前言 大家好久不见&#xff0c;今天是我…

22.1.29打卡 2023牛客寒假算法基础集训营1 ACDHKLM

2023牛客寒假算法基础集训营1_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ 网上高质量题解太多了, 我这就作为打卡日报随便写写 A 四个变量 a b记录两队得分 c d记录两队最多还能获得的得分 简单模拟 /* ⣿⣿⣿⣿⣿⣿⡷⣯⢿⣿⣷⣻⢯⣿⡽⣻⢿⣿⣿⣿⣿⣿⣿⣿⣿…