HTTP代理源代码

原创 2007年10月10日 17:03:00
#pragma hdrstop

//---------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

#define MAX_TOMEOUT 10000
#define MAX_SOCKET 5000
#define MAX_CHARBUFF 20480
#define MAX_HOSTNAME 256
#define DEFPORT 80
#define LISPORT 8471
#define DEFLISNUM 500
#define HEADLEN 7

DWORD WINAPI ProClientThread(LPVOID lpParam);
SOCKET SendHeadData(SOCKET ClientSocket,char *Msg,char *HMsg,int Datalen);
SOCKET GetServerAddr(char *Msg,int datalen);
//void ChangeSysInfo(char *Msg);
char * Get3Chars(char * Str,int *len);
void RecvSendData(SOCKET Rsck,SOCKET Ssck,char *SendBuf);
DWORD WINAPI RSThread(LPVOID lpParam);

char ErrorSendMsg[]="Http/1.1 403 Forbidden/r/n/r/n<body><h1>403 Forbidden</h1></body>";

struct sendofsck
{
SOCKET Rsck;
SOCKET Ssck;
char *Buff;
};

int main(int argc, char* argv[])
{
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2), &WSAData))
return 1;

SOCKET ProServer= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ProServer == SOCKET_ERROR)
return 1;

struct sockaddr_in ServerStk={0}, ClientCont={0};

ServerStk.sin_family = AF_INET;//inter模式
ServerStk.sin_port = htons(LISPORT);//监听端口
ServerStk.sin_addr.S_un.S_addr = INADDR_ANY;

if(bind(ProServer, (LPSOCKADDR) & ServerStk, sizeof(ServerStk)) == SOCKET_ERROR)
return 1;

if(listen(ProServer, DEFLISNUM) == SOCKET_ERROR)
return 1;

int ServerStkSize = sizeof(ClientCont);
SOCKET ServerBegin[MAX_SOCKET];
DWORD funid;
int i=0;
while(1)
{
ServerBegin[i] = accept(ProServer, (struct sockaddr *)&ClientCont, &ServerStkSize);
if(ServerBegin[i] == INVALID_SOCKET)
return 1;

//建立用户线程
if(CreateThread(NULL, 0, ProClientThread, (LPVOID)&ServerBegin[i], 0, &funid) == 0)
continue;

if(i++ > MAX_SOCKET) i = 0;
}
}
//---------------------------------------------------------------------------
DWORD WINAPI ProClientThread(LPVOID lpParam)
{
SOCKET ClientConSock = (SOCKET)*(SOCKET*)lpParam;

//以上是接受变量
char *ReceiveBuf = (char*)malloc(sizeof(char)*MAX_CHARBUFF);
char *SenderBuf = (char *)malloc(sizeof(char)*MAX_CHARBUFF);
char HeadBuf[MAX_HOSTNAME] = "";
memset(ReceiveBuf,0,MAX_CHARBUFF);
memset(SenderBuf,0,MAX_CHARBUFF);

int DataLen = 0,SendLen = 0,fags = 0,HedLen = 0;

//获取第一次的数据信息
DataLen = recv(ClientConSock,ReceiveBuf,MAX_CHARBUFF,0);

if(DataLen != SOCKET_ERROR && DataLen != 0)
{


//判断是何种服务器动作
if(!strncmpi(ReceiveBuf,"GET ",4))
{
strncpy(SenderBuf,ReceiveBuf,4);
SendLen = 4;
fags = 1;
}
else if(!strncmpi(ReceiveBuf,"HEAD ",5))
{
strncpy(SenderBuf,ReceiveBuf,5);
SendLen = 5;
fags = 2;
}
else if(!strncmpi(ReceiveBuf,"POST ",5))
{
strncpy(SenderBuf,ReceiveBuf,5);
SendLen = 5;
fags = 3;
}
else
{
send(ClientConSock,ErrorSendMsg,strlen(ErrorSendMsg),0);
goto ext;
}
//判断是不是以http打头的数据
if(strncmpi(ReceiveBuf+SendLen,"http://",HEADLEN))
{
send(ClientConSock,ErrorSendMsg,strlen(ErrorSendMsg),0);
goto ext;
}
//获得http://和/之间的数据,也就是域名
char * Getfp = Get3Chars(ReceiveBuf+SendLen+HEADLEN,&HedLen);

if(Getfp == NULL)
{
send(ClientConSock,ErrorSendMsg,strlen(ErrorSendMsg),0);
goto ext;
}

//获得域名信息,比如www.163.com
memcpy(HeadBuf,ReceiveBuf+SendLen+HEADLEN,HedLen);
//简单构造一个去掉了域名的请求报文
memcpy(SenderBuf+SendLen,Getfp,DataLen-HedLen-HEADLEN);

//sendheaddata函数用来确定主机位置,创建socket句柄和发送第一批数据
SOCKET ServerSocket = SendHeadData(ClientConSock,SenderBuf,HeadBuf,DataLen-HedLen+SendLen);

//POST方式则新建一线程用来发送,同时调用recvsenddata函数用来接受

if(ServerSocket != SOCKET_ERROR)
{
//何种动作
if(fags == 1||fags == 2)
//接受服务器发来的数据
RecvSendData(ServerSocket,ClientConSock,SenderBuf);
else if(fags == 3)
{
//准备线程的参数,用结构传递
struct sendofsck SendSck={0};
SendSck.Rsck = ClientConSock;
SendSck.Ssck = ServerSocket;
SendSck.Buff = ReceiveBuf;
DWORD funid;
//建立线程来接受post剩下的数据,然后调用函数接受服务器发来的数据
if(CreateThread(NULL, 0, RSThread, (LPVOID)&SendSck, 0, &funid) != 0)
RecvSendData(ServerSocket,ClientConSock,SenderBuf);
}
closesocket(ServerSocket);
}
}
else
send(ClientConSock,ErrorSendMsg,strlen(ErrorSendMsg),0);

//退出信息
ext:closesocket(ClientConSock);
free(ReceiveBuf);
free(SenderBuf);
return 0;
}
//---------------------------------------------------------------------------
SOCKET SendHeadData(SOCKET ClientSocket,char *Msg,char *HMsg,int DataLen)
{
//char *SendBuf = Msg;
//int sendlen = DataLen;

//获得头部信息(此函数包括连接服务器功能)
SOCKET ServerSocket = GetServerAddr(HMsg,DataLen);
if(ServerSocket == SOCKET_ERROR)
return SOCKET_ERROR;

//修改头部
//ChangeSysInfo(SendBuf);

//发送第一次的数据给服务器
if(send(ServerSocket,Msg,DataLen,0) == SOCKET_ERROR)
{
closesocket(ServerSocket);
return SOCKET_ERROR;
}
return ServerSocket;
}
//---------------------------------------------------------------------------
SOCKET GetServerAddr(char *Msg,int datalen)
{
char HostIp[MAX_HOSTNAME]="";
int HostPort=0;

char *fp = Msg;
//如果有端口,则停下
for(int i = 0;i < MAX_HOSTNAME && *fp != ':' && *fp != '/0';i++)
HostIp[i]=*fp++;
//取出端口信息
if(*fp == ':')
HostPort=atoi(fp+1);
else HostPort=DEFPORT;

//申请并填充结构
struct sockaddr_in ServerAddr;

ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(HostPort);

//填充IP,如果是域名,则转换为IP
if(HostIp[0] >= '0' && HostIp[0] <= '9')
ServerAddr.sin_addr.s_addr = inet_addr(HostIp);
else
{
//域名转为IP
struct hostent *pHost = gethostbyname(HostIp);
if(!pHost)
return SOCKET_ERROR;
memcpy(&ServerAddr.sin_addr,pHost->h_addr_list[0],sizeof(ServerAddr.sin_addr));
}

//设置连接
SOCKET ServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(ServerSocket == SOCKET_ERROR)
return SOCKET_ERROR;

//设置超时
int time_out=MAX_TOMEOUT;
if(setsockopt(ServerSocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&time_out,sizeof(time_out)) == SOCKET_ERROR)
return SOCKET_ERROR;

//连接
if(connect(ServerSocket,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr)) == SOCKET_ERROR)
{
closesocket(ServerSocket);
return SOCKET_ERROR;
}

//返回连接句柄
return ServerSocket;
}
/*/---------------------------------------------------------------------------
void ChangeSysInfo(char *Msg)
{
//修改的具体选项
char HostBan[] = "User-Agent: Mozilla/4.0 (compatible; MSIE ";
char *fp = strstr(Msg,HostBan);
if(fp != NULL) strncpy(fp + strlen(HostBan),"8.8; Windows ZV",15);
}
//--------------------------------------------------------------------------- */
char * Get3Chars(char * Str,int *len)
{
//获得/之后的位置,也就是除去http和域名的那些
for(int i = 0;i < MAX_HOSTNAME-HEADLEN; i++)
{
if(Str[i] == '/')
{
*len = i;
return &Str[i];
}
}
return NULL;
}
//---------------------------------------------------------------------------
void RecvSendData(SOCKET Rsck,SOCKET Ssck,char *SendBuf)
{
//从a处接受信息发往b处
int sendlen = 100;
while(sendlen > 0)
{
if((sendlen = recv(Rsck,SendBuf,MAX_CHARBUFF,0)) <= 0)
break;
if(send(Ssck,SendBuf,sendlen,0) < 0)
break;
}
}
//---------------------------------------------------------------------------
DWORD WINAPI RSThread(LPVOID lpParam)
{
//接受到信息后,用相反的方向来从客户端接受剩下的post数据发往服务器
struct sendofsck SendSck={0};
memcpy((void*)&SendSck,lpParam,sizeof(SendSck));
RecvSendData(SendSck.Rsck,SendSck.Ssck,SendSck.Buff);
return 1;
}
//---------------------------------------------------------------------------
 

C/C++程序实现通过http代理访问网页内容

公司通过代理上网,C程序直接通过发http请求不能获取网页内容,故实现了下通过代理访问http网页的一个测试程序。 程序很简单,有几个重点 先通过socket直接连接代理服务器...
  • wodet
  • wodet
  • 2013年11月25日 18:07
  • 4285

HTTP代理服务器源代码

  • 2012年04月06日 16:25
  • 106KB
  • 下载

HTTP代理源码

  • 2015年11月24日 16:29
  • 3KB
  • 下载

代理服务器源代码

  • 2006年01月06日 09:50
  • 10KB
  • 下载

一个简单的HTTP代理服务器c语言实现

HTTP代理原理不难。相关协议的资料网上很多。 但是想要找一份现成的简单源码来参考却不容易。这两天下载了很多http proxy的源码,几乎都或多或少有些问题,不能直接使用。 所以最后还是下决心自...
  • tiankong_bear
  • tiankong_bear
  • 2015年08月26日 21:38
  • 2927

五大开源Web代理服务器的横向点评

Web代理软件转发HTTP请求时并不会改变数据流量。它们可以配置成透明代理,而无需客户端配置。它们还可以作为反向代理放在网站的前端;这样缓存服务器可以为一台或多台web服务器提供无限量的用户服务。为深...
  • English0523
  • English0523
  • 2016年07月12日 14:57
  • 4329

HTTP 代理原理及实现(一)

Web 代理是一种存在于网络中间的实体,提供各式各样的功能。现代网络系统中,Web 代理无处不在。我之前有关 HTTP 的博文中,多次提到了代理对 HTTP 请求及响应的影响。今天这篇文章,我打算谈谈...
  • zbuger
  • zbuger
  • 2016年06月20日 13:29
  • 1701

HTTP代理服务器软件和源代码

  • 2010年05月13日 20:45
  • 3KB
  • 下载

简易HTTP代理的实现

编写一个简易的HTTP代理服务器,步骤其实很简单:      1.设置一个监听套接字gListen_Socket;      2.每当接受到客户端的请求之后,我们构建一个新的线程来继续监听客户端的请求...
  • lishuhuakai
  • lishuhuakai
  • 2014年05月23日 12:30
  • 10977

自己开发的HTTP一个简单HTTP代理服务器 含源码

  • 2010年06月02日 09:40
  • 39KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HTTP代理源代码
举报原因:
原因补充:

(最多只允许输入30个字)