CHttpProxyServer

HttpProxy.h

#ifndef  HTTPROXY_HEAD_FILE
#define HTTPROXY_HEAD_FILE
#pragma once
#include <windows.h>
#include <stdio.h>
#include <wininet.h>
#include <errno.h>
#include <tchar.h>
#include <assert.h>
#pragma comment(lib,"Ws2_32.lib")


//删除指针
#define SafeDelete(pData){if (pData) {free(pData);pData=NULL;}} 
//关闭句柄删除指针
#define SafeCloseHandleDelete(pData){if (pData){closesocket(pData[0]);closesocket(pData[1]);free(pData);pData=NULL;}}



//宏定义
#define					MAX_HOSTNAME								1024			//最大主机名称
#define					DEFAULTPORT											80			//默认主机端口
#define					LISTENPORT											8000			//代理服务器监听端口
#define					DEFLISNUM												500			//linsten最大队列
#define					HEADLEN														7			//http://头长度
#define					TIMEOUT												10000			//recv延时时间	
#define					MAXSIZE												20480			//缓冲大小
#define					GET_STYLE														1			//get请求类型			请求指定的页面信息,并返回实体主体
#define					HEAD_STYLE													2			//head请求类型			只请求页面的首部
#define					POST_STYLE													3			//post请求类型			请求服务器接受所指定的文档作为对所标识的URI的新的从属实体
#define					CONNECT_STYLE											4			//connect请求类型
#define					ErrorMsg	"HTTP/1.1 403 Forbidden\r\n\r\n<body><h1>403 Forbidden</h1></body>"
#define					ConnectionEstablished		"HTTP/1.0 200 OK\r\n\r\n"

//char ErrorMsg[]="HTTP/1.1 403 Forbidden\r\n\r\n<body><h1>403 Forbidden</h1></body>";			//SOCK错误消息
//char ConnectionEstablished[]="HTTP/1.0 200 OK\r\n\r\n";																					//HTTP成功


//HTTP代理服务器
class CHttpProxyServer
{
	//变量定义
public:
	SOCKET												m_ProxyServer;					//sock句柄
	UINT													m_nPort;								//监听端口

	//静态变量
protected:
	static CHttpProxyServer *			m_pHttpProxyServer;				//对象指针

	//函数定义
public:
	//构造函数
	CHttpProxyServer();
	//析构函数
	~CHttpProxyServer();

	//辅助函数
protected:
	// 地址解释
	DWORD TranslateAddr(char* pszServerAddr);

	//功能函数
public:
	//启动服务
	BOOL OnStart(int nPort=LISTENPORT);
	//发送请求
	static BOOL  SendRequest(SOCKET* CSsocket, char *SenderBuf, char *ReceiveBuf, int DataLen);
	//查询请求
	static int   CheckRequest(char *ReceiveBuf,int *MethodLength);
	//修改请求 
	static int   ModifyRequest(char *SenderBuf,char *ReceiveBuf,int DataLen,int MethodLength);
	//获取根目录节点
	static char  *GetURLRootPoint(char * ReceiveBuf,int DataLen,int *HostNaneLen);
	//获取主机名和端口
	static void  GetHostNameAndPort(char *ReceiveBuf,int datalen,char *HostName,UINT *RemotePort);
	//连接远程主机
	static BOOL  ConnectToRemoteHost(SOCKET *ServerSocket,char *HostName,const UINT RemotePort);
	//主机名解析IP地址
	static char  *DNS(char *HostName);


	//线程函数
protected:
	//启动服务线程
	static DWORD   StartThread( LPVOID lpParameter);
	//HTTP代理线程
	static DWORD   ZXHTTPProxyThread(LPVOID lpParameter);
	//信息传递线程 
	static DWORD  TransferData(LPVOID lpParameter);

	//静态函数
public:
	//获取对象
	static CHttpProxyServer * GetInstance() { return m_pHttpProxyServer; }
};



#endif


HttpProxy.cpp

#include "HttpProxy.h"

//////////////////////////////////////////////////////////////////////////////////

//静态变量
CHttpProxyServer *			CHttpProxyServer::m_pHttpProxyServer=NULL;					//对象指针

//////////////////////////////////////////////////////////////////////////////////

//构造函数
CHttpProxyServer::CHttpProxyServer()
{
	//设置对象
	assert(m_pHttpProxyServer==NULL);
	if (m_pHttpProxyServer==NULL)m_pHttpProxyServer=this;

	//初始化变量
	m_ProxyServer=INVALID_SOCKET;
	m_nPort=LISTENPORT;

	//初始化网络库
	WSADATA WSAData;
	WSAStartup(MAKEWORD(2,2), &WSAData);
}

//析构函数
CHttpProxyServer::~CHttpProxyServer()
{
	WSACleanup( );
}

//启动服务
BOOL CHttpProxyServer::OnStart(int nPort)
{
	//参数效验
	assert(m_ProxyServer==INVALID_SOCKET);
	assert(nPort>0 && nPort<65535);
	if (m_ProxyServer!=INVALID_SOCKET)return FALSE;
	if (nPort<0 || nPort>=65535)return FALSE;

	//创建socket
	m_ProxyServer= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	assert(m_ProxyServer!=SOCKET_ERROR);
	if(m_ProxyServer == SOCKET_ERROR)return FALSE;

	//设置变量
	m_nPort=nPort;

	//创建线程启动服务
	HANDLE hThread=CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)StartThread,this,NULL,NULL);
	CloseHandle(hThread);

	return TRUE;
}


//启动服务线程
DWORD   CHttpProxyServer::StartThread( LPVOID lpParameter)
{
	//设置变量
	CHttpProxyServer* pHttpProxyServer=(CHttpProxyServer*)lpParameter;
	assert(pHttpProxyServer!=NULL);
	if (pHttpProxyServer==NULL)return false;

	//绑定端口
	struct sockaddr_in Server={0};
	Server.sin_family = AF_INET;
	Server.sin_port = htons(pHttpProxyServer->m_nPort);
	Server.sin_addr.S_un.S_addr = INADDR_ANY;
	if(bind(pHttpProxyServer->m_ProxyServer, (LPSOCKADDR)&Server, sizeof(Server)) == SOCKET_ERROR) return FALSE;


	//监听连接
	if(listen(pHttpProxyServer->m_ProxyServer, DEFLISNUM) == SOCKET_ERROR)return FALSE;

	//定义变量
	SOCKET AcceptSocket = INVALID_SOCKET;
	SOCKET *CSsocket=NULL;
	while(true)
	{
		//接受客户端连接
		AcceptSocket = accept(pHttpProxyServer->m_ProxyServer, NULL, NULL);
		CSsocket = (SOCKET*)malloc(sizeof(SOCKET)*2);
		if (CSsocket == NULL)continue;

		//创建线程处理客户端连接请求
		CSsocket[0] = AcceptSocket;
		HANDLE hThread = CreateThread (NULL,0, (LPTHREAD_START_ROUTINE)ZXHTTPProxyThread,CSsocket,NULL,NULL); 
		if (hThread == NULL) Sleep(1000);
		else CloseHandle(hThread);
	}

	return true;
}

//HTTP代理线程
DWORD   CHttpProxyServer::ZXHTTPProxyThread(LPVOID lpParameter)
{
	//设置变量
	SOCKET* CSsocket=(SOCKET*)lpParameter;
	assert(CSsocket!=NULL);
	if (CSsocket==NULL)return false;

	//分配内存
	char *ReceiveBuf = (char*)malloc(sizeof(char)*MAXSIZE);
	char *SenderBuf  = (char*)malloc(sizeof(char)*MAXSIZE);
	memset(ReceiveBuf,0,MAXSIZE);
	memset( SenderBuf,0,MAXSIZE);

	//接受数据
	int DataLen = 0;
	DataLen = recv(CSsocket[0],ReceiveBuf,MAXSIZE,0);
	if(DataLen == SOCKET_ERROR || DataLen == 0)
	{
		SafeDelete(ReceiveBuf);
		SafeDelete(SenderBuf);
		SafeCloseHandleDelete(CSsocket);
		return 0;
	}

	//发送请求
	if(SendRequest(CSsocket, SenderBuf, ReceiveBuf, DataLen)==FALSE)
		send(CSsocket[0],ErrorMsg,strlen(ErrorMsg),0);


	//清理资源
	SafeDelete(ReceiveBuf);
	SafeDelete(SenderBuf);
	SafeCloseHandleDelete(CSsocket);
	return true;
}

//发送请求
BOOL  CHttpProxyServer::SendRequest(SOCKET* CSsocket, char *SenderBuf, char *ReceiveBuf, int DataLen)
{
	//参数效验
	assert(CSsocket!=NULL);
	assert(SenderBuf!=NULL);
	assert(ReceiveBuf!=NULL);
	assert(DataLen>0);
	if (CSsocket==NULL)return false;
	if (SenderBuf==NULL)return false;
	if (ReceiveBuf==NULL)return false;
	if (DataLen<0)return false;


	//CSsocket[0] ClientSocket			//客户端socket
	//CSsocket[1] ServerSocket			//服务端socket

	//定义变量
	char   HostName[MAX_HOSTNAME] = {0};
	UINT   RemotePort = 0;
	int Flag=0, MethodLength=0, SendLength=0;

	//查询请求
	Flag = CheckRequest(ReceiveBuf,&MethodLength);
	if(Flag==0) return 0;

	if(Flag==GET_STYLE || Flag==HEAD_STYLE || Flag==POST_STYLE)
	{
		//修改请求 
		SendLength=ModifyRequest(SenderBuf,ReceiveBuf,DataLen,MethodLength);
		if(SendLength==NULL)return 0;

		//获取主机名和端口
		GetHostNameAndPort(ReceiveBuf+MethodLength+HEADLEN,DataLen-MethodLength-HEADLEN,HostName,&RemotePort);

		//连接远程主机	//pc.qq.com 80
		if(ConnectToRemoteHost(&CSsocket[1],HostName,RemotePort)==FALSE)return 0;

		//发送数据		//这里是向服务器请求域名后面的页面,比如http://pc.qq.com/all.html  实际请求的是all.html
		if(send(CSsocket[1],SenderBuf,SendLength,0) == SOCKET_ERROR) return 0;
	}
	else if(Flag==CONNECT_STYLE)
	{
		//获取主机名和端口
		GetHostNameAndPort(ReceiveBuf+MethodLength,DataLen-MethodLength,HostName,&RemotePort);

		//连接远程主机
		if(ConnectToRemoteHost(&CSsocket[1],HostName,RemotePort)==FALSE) return 0;

		//发送数据
		send(CSsocket[0], ConnectionEstablished, strlen(ConnectionEstablished),0);
	}

	//转发线程
	if(CSsocket[0] && CSsocket[1])
	{
		//开启线程
		HANDLE ThreadHandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)TransferData,CSsocket,NULL,NULL);
		if (ThreadHandle != NULL)WaitForSingleObject(ThreadHandle, INFINITE);
		CloseHandle(ThreadHandle); 	
	}
	else	return FALSE;


	return TRUE;
}

//查询请求	返回请求的类型
int   CHttpProxyServer::CheckRequest(char *ReceiveBuf,int *MethodLength)
{
	//参数效验
	assert(ReceiveBuf!=NULL);
	assert(MethodLength!=NULL);
	if (ReceiveBuf==NULL)return NULL;
	if (MethodLength==NULL)return NULL;

	if(! _strnicmp(ReceiveBuf,"GET ",4))
	{
		*MethodLength = 4;
		return GET_STYLE;
	}
	else if(! _strnicmp(ReceiveBuf,"HEAD ",5)) //Looks like the same with GET
	{
		*MethodLength = 5;
		return HEAD_STYLE;
	}
	else if(! _strnicmp(ReceiveBuf,"POST ",5))
	{
		*MethodLength = 5;
		return POST_STYLE;
	}
	else if(! _strnicmp(ReceiveBuf,"CONNECT ",8))
	{
		*MethodLength = 8;
		return CONNECT_STYLE;
	}
	else
	{
		return 0;
	}

	return 0;
}

//修改请求    返回域名后面的路径
int   CHttpProxyServer::ModifyRequest(char *SenderBuf,char *ReceiveBuf,int DataLen,int MethodLength)
{
	//参数效验
	assert(SenderBuf!=NULL);
	assert(ReceiveBuf!=NULL);
	assert(DataLen>0);
	assert(MethodLength>0);
	if (SenderBuf==NULL)return NULL;
	if (ReceiveBuf==NULL)return NULL;
	if (DataLen<0)return NULL;
	if (MethodLength<0)return NULL;

	//设置变量
	strncpy(SenderBuf,ReceiveBuf,MethodLength);
	int HedLen = 0;

	//http头判断
	if(strncmp(ReceiveBuf+MethodLength,"http://",HEADLEN)) return 0;

	//获取域名后面的部分
	char * Getrootfp = GetURLRootPoint(ReceiveBuf+MethodLength+HEADLEN,DataLen
		-MethodLength-HEADLEN,&HedLen);
	if(Getrootfp == NULL)
		return 0;

	memcpy(SenderBuf+MethodLength,Getrootfp,DataLen-MethodLength-HEADLEN-HedLen);

	//返回长度
	return DataLen-HEADLEN-HedLen;
}

//获取根目录节点  获取域名后面的部分
char* CHttpProxyServer::GetURLRootPoint(char * ReceiveBuf,int DataLen,int *HostNaneLen)
{
	//参数效验
	assert(DataLen>0);
	assert(ReceiveBuf!=NULL);
	assert(HostNaneLen!=NULL);
	if (DataLen<0)return NULL;
	if (ReceiveBuf==NULL)return NULL;
	if (HostNaneLen==NULL)return NULL;


	//解析操作
	for(int i = 0;i < DataLen; i++)
	{
		if(ReceiveBuf[i] == '/')
		{
			*HostNaneLen = i;
			return &ReceiveBuf[i];
		}
	}
	return NULL;
}

//获取主机名和端口
void  CHttpProxyServer::GetHostNameAndPort(char *ReceiveBuf,int datalen,char *HostName,UINT *RemotePort)
{

	//参数效验
	assert(datalen>0);
	assert(RemotePort!=NULL);
	assert(HostName!=NULL);
	if (datalen<0)return;
	if (RemotePort==NULL)return;
	if (HostName==NULL)return;


	//解析主机端口
	char *fp = ReceiveBuf;
	for(int i = 0;i < datalen && *fp != ':' && *fp != '\0' && *fp != '\r' && *fp != '/';i++)
	{    
		//解析主机
		HostName[i]=*fp++;

		//解析端口
		if(*fp == ':') *RemotePort=atoi(fp+1);
		else *RemotePort=DEFAULTPORT;
	}

	return;
}

//连接远程主机
BOOL  CHttpProxyServer::ConnectToRemoteHost(SOCKET *ServerSocket,char *HostName,const UINT RemotePort)
{
	//参数效验
	assert(*ServerSocket!=SOCKET_ERROR);
	assert(HostName!=NULL);
	assert(RemotePort>0);
	if (*ServerSocket==SOCKET_ERROR)return false;
	if (*HostName==NULL)return false;
	if (RemotePort<0)return false;

	//地址信息
	sockaddr_in Server={0};
	Server.sin_family = AF_INET;
	Server.sin_port = htons(RemotePort);
	if (inet_addr(HostName) != INADDR_NONE)
	{
		Server.sin_addr.s_addr = inet_addr(HostName);
	}
	else
	{
		//解析主机地址
		if (DNS(HostName) != NULL)
		{
			Server.sin_addr.s_addr = inet_addr(DNS(HostName));
		}
		else
		{
			assert(FALSE);
			return FALSE;
		}
	}

	//创建socket
	*ServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (*ServerSocket == INVALID_SOCKET) return FALSE;

	//设置socket接收的超时时间为10秒 
	UINT TimeOut = TIMEOUT;
	setsockopt(*ServerSocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut));

	// 连接远程主机
	if (connect(*ServerSocket, (const SOCKADDR *)&Server,sizeof(Server)) == SOCKET_ERROR)
	{
		closesocket(*ServerSocket);
		return FALSE;
	}

	return TRUE;
}

//主机名解析IP地址
char* CHttpProxyServer::DNS(char *HostName)
{
	//参数效验
	assert(HostName);
	if (HostName==NULL)return NULL;

	//获取主机地址
	HOSTENT *hostent = NULL;
	IN_ADDR iaddr;
	hostent = gethostbyname(HostName);
	if (hostent == NULL)return NULL;

	iaddr = *((LPIN_ADDR)*hostent->h_addr_list);
	return inet_ntoa(iaddr);
}

//信息传递线程 
DWORD  CHttpProxyServer::TransferData(LPVOID lpParameter)
{
	//参数效验
	SOCKET* CSsocket=(SOCKET*)lpParameter;
	assert(CSsocket!=NULL);
	if (CSsocket==NULL)return false;


	//定义变量
	SOCKET ClientSocket = CSsocket[0];
	SOCKET ServerSocket = CSsocket[1];
	timeval timeset={0};			//超时时间
	fd_set readfd,writefd;
	int result,i=0;
	char read_in1[MAXSIZE]={0};
	char send_out1[MAXSIZE]={0};
	char read_in2[MAXSIZE]={0};
	char send_out2[MAXSIZE]={0};		//ServerSocket套接字接受数据
	char SenderBuf[MAXSIZE]={0};
	int read1=0;
	int Clienttotalread1=0;				//ClientSocket套接字接受长度
	int send1=0;
	int read2=0;
	int Servertotalread2=0;				//ServerSocket套接字接受长度
	int send2=0;
	int sendcount1=0;
	int sendcount2=0;
	int maxfd=0;						//最大套接字范围

	maxfd=max(ClientSocket,ServerSocket)+1;
	memset(read_in1,0,MAXSIZE);
	memset(read_in2,0,MAXSIZE);
	memset(send_out1,0,MAXSIZE);
	memset(send_out2,0,MAXSIZE);

	timeset.tv_sec=TIMEOUT;
	timeset.tv_usec=0;
	while(true)
	{
		//初始化为空集合
		FD_ZERO(&readfd);
		FD_ZERO(&writefd);

		//添加套接字到集合
		FD_SET((UINT)ClientSocket, &readfd);
		FD_SET((UINT)ClientSocket, &writefd);
		FD_SET((UINT)ServerSocket, &writefd);
		FD_SET((UINT)ServerSocket, &readfd);

		//查询事件
		result=select(maxfd,&readfd,&writefd,NULL,×et);
		if((result<0) && (errno!=EINTR)) break;
		else if(result==0) break;

		//1.接受远程服务端数据
		if(FD_ISSET(ServerSocket, &readfd))		//检查s是不是set的成员,如果是返回TRTUE  
		{
			//fx 2016年5月17日16:18:03
			//由于已近连接了远程服务器,所有会先收到服务器的数据
			//收到服务器返回http://pc.qq.com/all.html
			//最大长度判断
			if(Servertotalread2<MAXSIZE)
			{
				read2=recv(ServerSocket,read_in2,MAXSIZE-Servertotalread2, 0);
				if(read2==0)break;
				if((read2<0) && (errno!=EINTR)) break;

				memcpy(send_out2+Servertotalread2,read_in2,read2);
				Servertotalread2+=read2;
				memset(read_in2,0,MAXSIZE);
			}

		}

		//2.转发数据到客户端
		if(FD_ISSET(ClientSocket, &writefd))		//检查s是不是set的成员,如果是返回TRTUE  
		{
			//收到远程服务器的数据直接转发给客户端
			//1和2相当于是一套组合,收到远程服务器的数据转发到客户端
			//http://pc.qq.com/all.html发送到客户端
			int err2=0;
			sendcount2=0;
			while(Servertotalread2>0)		//接受长度
			{
				send2=send(ClientSocket, send_out2+sendcount2, Servertotalread2, 0);
				if(send2==0)break;
				if((send2<0) && (errno!=EINTR))
				{
					err2=1;
					break;
				}
				if((send2<0) && (errno==ENOSPC)) break;
				sendcount2+=send2;
				Servertotalread2-=send2;

			}
			if(err2==1) break;
			if((Servertotalread2>0) && (sendcount2 > 0))
			{
				/* move not sended data to start addr */
				memcpy(send_out2, send_out2+sendcount2, Servertotalread2);
				memset(send_out2+Servertotalread2, 0, MAXSIZE-Servertotalread2);
			}
			else	memset(send_out2,0,MAXSIZE);
		}

		//3.接受客户端请求
		if(FD_ISSET(ClientSocket, &readfd))			//检查s是不是set的成员,如果是返回TRTUE  
		{
			//是否收到客户端数据,如果有接受客户端发来的请求
			//客户端请求比如http://pc.qq.com/all.html
			if(Clienttotalread1<MAXSIZE)
			{
				read1=recv(ClientSocket, read_in1, MAXSIZE-Clienttotalread1, 0);
				if((read1==SOCKET_ERROR) || (read1==0)) break;

				memcpy(send_out1+Clienttotalread1,read_in1,read1);
				Clienttotalread1+=read1;
				memset(read_in1,0,MAXSIZE);
			}

			//发送请求  到远程服务器比如http://pc.qq.com/all.html
			if(SendRequest(CSsocket,SenderBuf,send_out1,Clienttotalread1))
				Clienttotalread1=0;
		}

		//2.收到客户端请求转发到服务器
		if(FD_ISSET(ServerSocket, &writefd))
		{
			//发送请求  到远程服务器比如http://pc.qq.com/all.html
			int err=0;
			sendcount1=0;
			while(Clienttotalread1>0)
			{
				send1=send(ServerSocket, send_out1+sendcount1, Clienttotalread1, 0);
				if(send1==0)break;
				if((send1<0) && (errno!=EINTR))
				{
					err=1;
					break;
				}

				if((send1<0) && (errno==ENOSPC)) break;
				sendcount1+=send1;
				Clienttotalread1-=send1;
			}

			if(err==1) break;
			if((Clienttotalread1>0) && (sendcount1>0))
			{
				memcpy(send_out1,send_out1+sendcount1,Clienttotalread1);
				memset(send_out1+Clienttotalread1,0,MAXSIZE-Clienttotalread1);
			}
			else
				memset(send_out1,0,MAXSIZE);
		}
		Sleep(5);
	}

	closesocket(ClientSocket);
	closesocket(ServerSocket);

	return true;
}

// 地址解释
DWORD CHttpProxyServer::TranslateAddr(char* pszServerAddr)
{
	// 转化地址
	DWORD dwServerIP = inet_addr(pszServerAddr);

	if (dwServerIP == INADDR_NONE)
	{
		LPHOSTENT lpHost = gethostbyname(pszServerAddr);
		if (lpHost == NULL) return INADDR_NONE;
		dwServerIP = ((LPIN_ADDR)lpHost->h_addr)->s_addr;
	}
	return dwServerIP;
}


main.cpp

#include "HttpProxy.h"

int main (void)
{
	CHttpProxyServer	httpProxyServer;
	httpProxyServer.OnStart();

	getchar();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值