编程实战:自己编写HTTP服务器(系列6:调用用户功能)

初级代码游戏的专栏介绍与文章目录-CSDN博客 

系列入口:编程实战:自己编写HTTP服务器(系列1:概述和应答)-CSDN博客

         本文讲解如何将原有C++代码接入到WEB服务里。

目录

一、概述

二、框架入口

三、执行用户功能

3.1 代码

3.2 入口参数

3.3 系统检查和初始化

3.4 执行

四、接口


一、概述

        做嵌入式服务器的主要目的当然不是提供静态文件,而是将程序里的功能和浏览器结合起来,让浏览器成为程序的用户界面。用浏览器直接调用程序功能显然比查日志文件或者数据库友好多了。用浏览器直接操作程序也比修改配置文件再重启程序方便很多倍。

        命令接口最基础的就是一个函数指针或者虚函数,提前配置好函数指针或虚函数,框架只需要调用函数指针或虚函数即可。主要的工作是制定合理的输入输出参数。

二、框架入口

        框架中根据请求的资源目录和扩展名来确定是否是用户功能:

        从上面的代码可以看出来,资源是“/bin/”或者“/admin/”目录(虚拟目录)下的就执行用户功能。扩展名为“asp”、“aspx”、“asmx”的当作内置页面(显然这是我在模仿IIS,这些后缀名与它们通常的意义毫无关系),其余当作CGI,当然了CGI已经没人写了,所以可以无视。

        doPageFunction()的代码是这样的:

        首先查找了命令, 然后根据命令的属性做了一些区别,实质的执行代码是_doPageFunction()。如果有错误就返回404或500。

        其余代码不用关心。你当然也会在自己的程序里加入很多特定功能。

三、执行用户功能

3.1 代码

		bool _doPageFunction(web_command_private_struce * pCmdInfo)
		{
			long i_cmd = pCmdInfo->seq;
			CWebCommand * pCmd = pCmdInfo->pWebCommand;
			//处理用户系统内部检查
			string err;
			if (NULL != this->pfCheckSys && !pfCheckSys(err))
			{
				//用户系统检查未通过,不执行用户函数
				OnPageStart("500 Internal Server Error");
				m_respond.AppendBody(CHtmlDoc::HTMLEncode(err));
				OnPageEnd();
				return false;
			}

			++m_pServerDatas->m_web_command_data_s[i_cmd].count;//执行计数

			if (!pCmdInfo->isInited)
			{
				if (!pCmd->InitWebFunction())
				{
					LOG << pCmd->command_id << " 初始化失败" << ENDE;
					OnPageStart("500 Internal Server Error");
					m_respond.AppendBody(CHtmlDoc::HTMLEncode(err));
					OnPageEnd();
					return false;
				}
				else
				{
					LOG << pCmd->command_id << " 初始化成功" << ENDI;
					pCmdInfo->isInited = true;
				}
			}

			if (pCmd->NotStdPage)
			{
				if (!pCmd->doWebFunction(&this->m_request, this->m_s, &this->m_respond))
				{
					++m_pServerDatas->m_web_command_data_s[i_cmd].count_err;//出错计数
				}
			}
			else
			{
				//文件头
				OnPageStart(pCmd->name.c_str());
				LOG << "发送应答头" << ENDI;
				if (!m_respond.Flush(m_s))return true;

				if (!CallCommand(pCmd))
				{
					++m_pServerDatas->m_web_command_data_s[i_cmd].count_err;//出错计数
				}

				//文件尾
				m_respond.AppendBody("<P><HR></HR>");
				m_respond.AppendBody(pCmd->name);
				m_respond.AppendBody("<BR>");
				m_respond.AppendBody(pCmd->note);
				m_respond.AppendBody("<BR>");
				if (!pCmd->hide)
				{
					pCmd->SetParamValueFromRequest(m_request);
					m_respond.AppendBody(pCmd->toHtmlFormInput(false, false, &m_request));
					m_respond.AppendBody("<INPUT TYPE=\"hidden\" NAME=\"autorefresh\" >\n");
					m_respond.AppendBody(pCmd->toHtmlFormSubmit(true));

					if (pCmd->AutoRefresh)
					{
						char buf2[2048];
						bool isAutoRefresh = (m_request.GetParam("autorefresh") == "true");
						long refreshtimeout = atol(m_request.GetParam("refreshtimeout").c_str());
						if (refreshtimeout <= 0)refreshtimeout = 10;
						sprintf(buf2,
							"<BUTTON NAME=\"autorefresh\" onclick=\"timer=setTimeout('window.%s.submit()',%ld);window.%s.autorefresh.value='true';window.autorefresh.disabled=true;window.stoprefresh.disabled=false;\">自动刷新</BUTTON>\n"
							"<button NAME=\"stoprefresh\" disabled onclick=\"clearTimeout(timer);window.%s.autorefresh.value='';window.autorefresh.disabled=false;window.stoprefresh.disabled=true;\">停止刷新</BUTTON><BR>\n"
							"%s<BR>\n"
							, pCmd->GetFormName().c_str(), refreshtimeout * 1000, pCmd->GetFormName().c_str(), pCmd->GetFormName().c_str(), (isAutoRefresh ? "<script language=\"JavaScript\">window.autorefresh.onclick()</script>" : ""));
						m_respond.AppendBody(buf2);
					}
				}
				OnPageEnd();
			}
			return true;
		}

3.2 入口参数

        入口参数web_command_private_struce里面主要就是接口对象,一个函数指针或者虚函数。

        请求对象和应答对象都是类成员,在类里面可以随时使用,但是用户功能是外部的,所以要在调用时作为参数传递。

3.3 系统检查和初始化

        调用外部功之前执行了外部提供的系统检查pfCheckSys,如果失败就不能执行用户功能。

        每个用户功能可能需要初始化。所以第一调用要先初始化。

        如果功能够简单,这两步都可以忽略。

3.4 执行

        执行分两种,一种是嵌入在标准HTML页面里面,用户功能只提供主体输出,另一种是用户功能完全控制输出(比如一张动态刷新页面内容的无限网页,后面我会介绍如何实现)。

        标准页面由框架生成HTML的首尾部分,可以具有相同的辅助功能,中间调用CallCommand输出内容,纯自定义输出则执行“pCmd->doWebFunction(&this->m_request, this->m_s, &this->m_respond)”,CallCommand其实也是执行这个,只不过略加一点控制。

        剩下的核心就是doWebFunction了。

四、接口

        待续。

(这里是结束,但不是整个系列的结束)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

初级代码游戏

知识究竟是有价还是无价

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

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

打赏作者

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

抵扣说明:

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

余额充值