一个http代理的代码

来源:互联网 发布:淘宝男士钱包在哪 编辑:程序博客网 时间:2024/05/14 07:30
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <process.h>
#include <windows.h>
#include <assert.h>
#define  MAXBUFLEN  20480
#define  HTTPADDLEN 50
#define  TIMEWAIT   2000
SOCKET   Global[1000000];

void  DisplayBanner();
void  Proxy( void * pSocket);
int   ParseHttpRequest(char * SourceBuf,int DataLen,void * ServerAddr);
void  ParseError(char * ErrorMsg);

int main(int argc,char * argv[])
{
    SOCKET  MainSocket,ClientSocket;
    struct  sockaddr_in Host,Client;
    WSADATA WsaData;
    int  AddLen,i;

    //初始化
    DisplayBanner();
    if(WSAStartup(MAKEWORD(2,2),&WsaData) < 0)
    {
        printf("dll load errorn");
        exit(-1);
    }
    //创建socket端口
    MainSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(MainSocket == SOCKET_ERROR)
    {
        ParseError("端口创建错误");
    }
    Host.sin_family = AF_INET;
    Host.sin_port = htons(8080);
    Host.sin_addr.s_addr = inet_addr("159.226.39.116");
    printf("正在工作n");
    //邦定
    if(bind(MainSocket,(SOCKADDR *)&Host,sizeof(Host)) != 0)
    {
        ParseError("邦定错误");
    }
    i = 0;
    //监听
    if(listen(MainSocket,5) == SOCKET_ERROR)
    {
        ParseError("监听错误");
    }
    AddLen = sizeof(Client);

    //连接新的客户
    i = 0;
    while(1)
    {
        ClientSocket = accept(MainSocket,(SOCKADDR *)&Client,&AddLen);
        if(ClientSocket == SOCKET_ERROR)
        {
            ParseError("接受客户请求错误");
        }
        printf(".");
        i ++ ;
        if( i >= 1000000)
            i = 0;
        Global[i] = ClientSocket;

        //对于每一个客户启动不同的进程进行控制
        //这个地方在使用ClientSocket的时候,要不要保证在某一时刻内只能有一个进程使用?    
        _beginthread(Proxy,0,(void *)&Global[i]);
        
    }

    

}
void Proxy( void * pSocket)
{
    SOCKET ClientSocket;
    char  ReceiveBuf[MAXBUFLEN];
    int  DataLen;
    struct sockaddr_in  ServerAddr;
    SOCKET  ProxySocket;
    int i = 0;
    int time = TIMEWAIT;

    //得到参数中的端口号信息
    ClientSocket = (SOCKET)* (SOCKET*)pSocket;
//接受第一次请求信息
    memset(ReceiveBuf,0,MAXBUFLEN);
    DataLen = recv(ClientSocket,ReceiveBuf,MAXBUFLEN,0);

    if(DataLen == SOCKET_ERROR)
    {
        ParseError("错误n");
        closesocket(ClientSocket);
        _endthread();
    }
    if(DataLen == 0)
    {
        closesocket(ClientSocket);
        _endthread();
    }    
    //处理请求信息,分离出服务器地址
    if( ParseHttpRequest(ReceiveBuf,DataLen,(void *)&ServerAddr) < 0)
    {
        closesocket(ClientSocket);
        goto error;
    }
    //创建新的socket用来和服务器进行连接
    ProxySocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    //设置超时时间
    setsockopt(ProxySocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&time,sizeof(time));
    if(ProxySocket == SOCKET_ERROR)
    {
        ParseError("端口创建错误");
        _endthread();
    }
    if(connect(ProxySocket,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr)) == SOCKET_ERROR)
    {
        //ParseError("连接服务器错误");
        goto error;
    }
    //开始进行数据传输处理
    //发送到服务器端
    if(send(ProxySocket,ReceiveBuf,DataLen,0) == SOCKET_ERROR)
    {
        //ParseError("数据发送错误");
        goto error;

    }
        //从服务器端接受数据
    while(DataLen > 0)
    {
        memset(ReceiveBuf,0,MAXBUFLEN);
    
        if((DataLen = recv(ProxySocket,ReceiveBuf,MAXBUFLEN,0)) <= 0)
        {
            //    ParseError("数据接受错误");
            break;
            
        }
        else
            //发送到客户端
            if(send(ClientSocket,ReceiveBuf,DataLen,0) < 0)
            {
                //    ParseError("数据发送错误");
                    break;
            }
        
    }
    
error:
    closesocket(ClientSocket);
    closesocket(ProxySocket);
    _endthread();
    return;

}
int  ParseHttpRequest(char * SourceBuf,int DataLen,void * ServerAddr)
{

    char * HttpHead = "http://";
    char * FirstLocation = NULL;
    char * LastLocation = NULL;
    char * PortLocation = NULL;
    char  ServerName[HTTPADDLEN];
    char  PortString[10];
    int   NameLen;
    struct hostent * pHost;
    struct sockaddr_in * pServer = (struct sockaddr_in *)ServerAddr;
    //取得http://的位置
    FirstLocation = strstr(SourceBuf,HttpHead) + strlen(HttpHead);
    //取得/的位置
    LastLocation = strstr(FirstLocation,"/");

    //得到http://和/之间的服务器的名称
    
    memset(ServerName,0,HTTPADDLEN);
    memcpy(ServerName,FirstLocation,LastLocation - FirstLocation);

    //有些情况下,请求的地址中带有端口号格式为“:+ 端口号”;
    //取得 :的位置
    PortLocation = strstr(ServerName,":");

    
    //填充server结构
    pServer->sin_family = AF_INET;
    //在url中制定了服务器端口
    if(PortLocation != NULL)
    {
        NameLen = PortLocation - ServerName -1;
        memset(PortString,0,10);
        memcpy(PortString,PortLocation + 1,NameLen);
        pServer->sin_port = htons((u_short)atoi(PortString));
        *PortLocation = 0;    
    }
    else//在url中,没有制定服务器端口
    {
        pServer->sin_port = htons(80);
    }

    if(NameLen > HTTPADDLEN)
    {
        ParseError("服务器名字太长");
        return -1;
    }
    
    //得到服务器信息
    //如果地址信息是以IP地址(202.194.7.1)的形式出现的
    if(ServerName[0] >= '0' && ServerName[0] <= '9')
    {
        
        pServer->sin_addr.s_addr = inet_addr(ServerName);
    }
    //以域名的形式出现的(www.sina.com.cn)
    else
    {
        pHost = (struct hostent *)gethostbyname(ServerName);
        if(!pHost)
        {
            printf("取得主机信息错误n");
            printf("%sn",ServerName);
            return -1;
        }
        memcpy(&pServer->sin_addr,pHost->h_addr_list[0],sizeof(pServer->sin_addr));
    }
    
    return 0;
}
void ParseError(char * ErrorMsg)
{
//    printf("%s %dn",ErrorMsg,GetLastError());
//    WSACleanup();
//    exit(-1);
}
void DisplayBanner()
{
    printf("=================================================n");
    printf("====                                         ====n");
    printf("====         HTTP PROXY v2.0                 ====n");
    printf("====        peijikui@ict.ac.cn               ====n");
    printf("====            Bug Patched                  ====n");
    printf("====            port 8080                    ====n");
    printf("====                                         ====n");
    printf("=================================================n");
}