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