导航

http代理源代码

Posted on 2004-11-27 18:47  charcs  阅读(1796)  评论(0编辑  收藏  举报
//---------------------------------------------------------------------------
//http代理源代码
//如果你做了修改,记得给我一封拷贝
//power by zvrop
//zvrop@163.com
//---------------------------------------------------------------------------
#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;
}
//---------------------------------------------------------------------------