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

本文介绍了一种在无外网连接的环境下通过自编译HTTP服务器实现文件从B机器到A机器的传输方法。该方法适用于Ubuntu 18.04系统,并依赖于libevent库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在项目中遇到过 通过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那里注释掉就可以了

如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QMCY_jason

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值