⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chttpsvr.cpp

📁 sun Linux 下的网络编程
💻 CPP
字号:
 /*******************************************************************
 *	cHttpsvr.cpp
 *    DESCRIPTION:chttpsvr类的实现文件
 *
 *    AUTHOR:yyc
 *
 *    HISTORY:
 *
 *    DATE:2002-6-28
 *
 *******************************************************************/
   
#include "cHttpsvr.h"
#include <memory>
#include <cstdio>

#include "logout.h"
RW_DEFINE_LOG("cHttpsvr")
using namespace std;
using namespace yyc;
/**
 * 添加URL和此URL的处理函数
 * 
 * @param url
 * @param pfunc
 * 
 * @return 
 */
int cHttpsvr::add_url(const char *url,FUNC_DOREQ *pfunc)
{
	int retv=0;
	if (url==NULL||url[0]==0||pfunc==NULL) return ENULL_SOCK;
	m_mapUrlfunc[url]=pfunc;
	retv=m_mapUrlfunc.size();
	return retv;
}
//得到某个url的处理地址
FUNC_DOREQ *cHttpsvr::get_url_addr(const char *url)
{
	FUNC_DOREQ *pfunc=NULL;
	if(m_mapUrlfunc.count(url)>=1)
	{
		pfunc=m_mapUrlfunc[url];
	}
	return pfunc;
}
/**
 * 从MAP表中删除某个URL的处理
 * 
 * @param url
 * 
 * @return 
 */
int cHttpsvr::del_url(const char *url)
{
	int retv=0;
	if (url==NULL||url[0]==0) return ENULL_SOCK;
	m_mapUrlfunc.erase(url);
	retv=m_mapUrlfunc.size();
	return retv;
}

/**
 * 启动http服务
 * 
 * @param port_p http服务端口,如果为0,则系统自动分配
 * 
 * @return http服务侦听端口,<0发生错误
 */
int cHttpsvr::start(int iPort)
{
	int retv=0;
	if (iPort>0) m_iPort=iPort;
	if (m_pSocksvr!=NULL) 
	{
		retv=m_pSocksvr->listen(m_iPort);
	}
	else
		retv=ENULL_SOCK;
	if(retv>=0)
	{
		m_iPort=retv;
		RW_LOG_DEBUG("HTTP server have started,port=%d\n",retv);
	}
	else
	{
		RW_LOG_DEBUG("HTTP server start failed,errno=%d\n",retv);
	}
	return retv;
}

/**
 * 停止http server
 * 
 * @return 
 */
int cHttpsvr::stop()
{
	if (m_pSocksvr!=NULL)
		m_pSocksvr->close();
	m_reqmap.clear();
	RW_LOG_DEBUG("HTTP server have stopped,port=%d\n",m_iPort);
	return 0;
}


/**
 * socket接收数据处理
 * 判断是否为http请求,创建HTTPREQ对象
 * 处理http请求,调用设定的URL处理函数
 * 此函数为csocket对象的回调函数
 * 
 * @param buf    收到数据的指针
 * @param len    收到数据大小
 * @param args   相关联的csocket对象指针
 * 
 * @return 详见csocket的接收数据处理回调函数说明
 */
int cHttpsvr::do_browserreq(char *buf,int len,cSocket *psock)
{
	int ret;
	cHttpsvr * phttpsvr=NULL;
	cHttpreq * phttpreq=NULL;

	if(NULL==buf||len<=0) return 1;//错误,关闭此socket
	if (NULL==psock) return 1;//错误,关闭此socket
	phttpsvr=(cHttpsvr *)psock->get_pArgs();
	if (NULL==phttpsvr) return 1;//错误,关闭此socket

	RW_LOG_DEBUG("HTTP Request:len=%d\n\t%s",len,buf);
	
	//判断是否为http请求头
	if (strncmp(buf,"GET",3)!=0&&strncmp(buf,"POST",4)!=0)
	{
		if((phttpreq=phttpsvr->m_reqmap.get(psock))!=NULL)
		{
			ret=phttpreq->do_reqdata(buf,len);
			if(ret>=0)
			{
				if (!phttpreq->is_end()) return 0;//数据未接收完,继续接收
				//删除映射表中的此选项,但并不释放value所指向空间
				phttpsvr->m_reqmap.remove(psock);
				//phhtpreq后续处理,处理完后会释放
			}
			else
			{
				phttpsvr->m_reqmap.remove(psock);
				RW_LOG_WARN("do_reqdata() return error,errno=%d\n",ret);
				//phhtpreq后续处理,处理完后会释放
			}//?if(ret>=0) else
		}//?if((phttpreq=phttpsvr->m_reqmap.get(psock))!=NULL)
		else
		{
			//无法定位到HTTP请求开始,接收错误的数据
			RW_LOG_WARN("receive wrong http request,len=%d\n",len);
			return 1;//错误,关闭此socket
		}
		
	}
	else
	{
		//如果是http请求头
		phttpreq=new(nothrow) cHttpreq;
		if(phttpreq!=NULL)
		{
			if((ret=phttpreq->do_reqdata(buf,len))>=0)
			{
				if (!phttpreq->is_end()){
					if(phttpsvr->m_reqmap.add(psock,phttpreq)<0)
					{
						delete phttpreq;phttpreq=NULL;
						RW_LOG_WARN("add cSocket *<----->HTTPREQ * MAP pair error!\n");
					}
					else
						return 0;//数据未接收完,继续接收
				}
				
			}//?if((ret=phttpreq->do_reqdata(buf,len))>=0)
			else
			{
				delete phttpreq;phttpreq=NULL;
				RW_LOG_WARN("[new] do_reqdata() return error,errno=%d\n",ret);
			}
		}//?if(phttpreq!=NULL)
		
	}//?是http请求头
	
	//请求处理
	if(phttpreq!=NULL) {
	   
		FUNC_DOREQ *pfunc=NULL;
		phttpreq->dump();
		
		if (phttpsvr->m_mapUrlfunc.count(phttpreq->m_strUrl)>=1)
			pfunc=phttpsvr->m_mapUrlfunc[phttpreq->m_strUrl];
		if (pfunc!=NULL) {
			psock->send("HTTP/1.1 200 OK\nContent-Type: text/html\n\n\n");
			ret=(*pfunc)(psock,phttpreq);
		}//?if (pfunc!=NULL)
		else
		{
				char *ptr=strchr(phttpreq->m_strUrl+1,'.');
				if (ptr!=NULL)
				{
					if (strcmp(ptr,".txt")==0||strcmp(ptr,".log")==0||strcmp(ptr,".c")==0||strcmp(ptr,".h")==0)
					{
						psock->send("HTTP/1.1 200 OK\nContent-Type: text/html\n\n\n");
						cHttpsvr::send_text_file(psock,phttpreq->m_strUrl+1);
					}
					else if (strcmp(ptr,".gif")==0||strcmp(ptr,".jpg")==0)
					{
						psock->send("HTTP/1.1 200 OK\nContent-Type: image/gif\nAccept-Ranges: bytes\n\n");
						cHttpsvr::send_file(psock,phttpreq->m_strUrl+1);
					}
					else
					{
						psock->send("HTTP/1.1 200 OK\nContent-Type: text/html\n\n\n");
						cHttpsvr::send_file(psock,phttpreq->m_strUrl+1);
					}
				}
				else  //其他文件
				{
					psock->send("HTTP/1.1 200 OK\nContent-Type: text/html\n\n\n");
					cHttpsvr::send_file(psock,phttpreq->m_strUrl+1);
				}
		}//?if (pfunc!=NULL) else
		
		delete phttpreq;
		//如果返回-1的话则不关闭
		if (ret==-1) return 0;
	}//?if(phttpreq!=NULL)
	else
		return 1;//错误,关闭此socket
	return 3;//发送数据并关闭socket
}

/**
 * 发送二进制文件
 * 
 * @param psock
 * @param filename
 */
void cHttpsvr::send_file(cSocket *psock,const char * filename)
{
    FILE * fd;
	char * ptr;
	int len=0;
	if (psock==NULL) return;
	if (filename==NULL) return;
	if (filename[0]==0) return;

	ptr=(char *)malloc(cBuffer::MAX_BUF_SIZE);
	memset((void *)ptr,0,cBuffer::MAX_BUF_SIZE);
	fd=fopen(filename,"rb");
	if (fd)
	{
		
		len=fread((void*)ptr,sizeof(char),cBuffer::MAX_BUF_SIZE,fd);
		while(len>0)
		{
			psock->send(len,ptr);
			if (len!=cBuffer::MAX_BUF_SIZE) break;
			len=fread((void*)ptr,sizeof(char),cBuffer::MAX_BUF_SIZE,fd);
		}
		fclose(fd);
	}
	else
		psock->send("Can not read file:%s!<br>", filename);
	free(ptr);

}

/**
 * 发送文本文件,将文件中的回车
 * 转化为"<BR>"
 * 
 * @param psock
 * @param filename
 */
void cHttpsvr::send_text_file(cSocket *psock,const char * filename)
{
	FILE * fd;
	char buf[DEFAULT_BUF_SIZE];//vc++ not surpport char[cBuffer::MAX_BUF_SIZE]
	int i,c,len=0;
	if (psock==NULL) return;
	if (filename==NULL) return;
	if (filename[0]==0) return;
	fd=fopen(filename,"rt");
	
	if (fd)
	{
		memset((char *)buf,0,cBuffer::MAX_BUF_SIZE);
		while(feof(fd)==0)
		{
			i=0;
            while(i<(cBuffer::MAX_BUF_SIZE-5))
			{
				c=fgetc(fd);
				if(c==10||c==EOF) break;
				buf[i++]=(char)c;
			}
			buf[i]='<';buf[i+1]='b';buf[i+2]='r';buf[i+3]='>';buf[i+4]=0;
			psock->send(buf);
		}
		fclose(fd);
	}
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -