zoukankan      html  css  js  c++  java
  • 黑客编程教程(十五)HTTP代理

    #include <stdio.h>  
    #include <winsock2.h> 
    
    #define  MAXBUFLEN  20480 
    
    #define  HTTPADDLEN 50 
    
    #define  TIMEWAIT   2000 
    
    #pragma comment(lib,"ws2_32.lib")
    
    SOCKET   Global[1000]; 
    
     
    
    DWORD WINAPI  Proxy( LPVOID pSocket); 
    
    int   ParseHttpRequest(char * SourceBuf,int DataLen,void * ServerAddr); 
    
     
    
     
    
    int main(int argc,char * argv[]) 
    
    { 
    
        SOCKET  MainSocket,ClientSocket; 
    
        struct  sockaddr_in Host,Client; 
    
        WSADATA WsaData; 
    
        int  AddLen,i; 
    
     
    
        //初始化 
    
       
    
        if(WSAStartup(MAKEWORD(2,2),&WsaData) < 0) 
    
        { 
    
            printf("初始化失败
    "); 
    
            return 1; 
    
        } 
    
        //创建socket端口 
    
        MainSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
    
        if(MainSocket == SOCKET_ERROR) 
    
        { 
    
            printf("端口创建错误
    ");
    
       return 1;
    
        } 
    
        Host.sin_family = AF_INET; 
    
        Host.sin_port = htons(8080); 
    
        Host.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    
        printf("正在工作
    "); 
    
        //绑定socket
    
        if(bind(MainSocket,(SOCKADDR *)&Host,sizeof(Host)) != 0) 
    
        { 
    
            printf("绑定错误
    ");
    
        } 
    
        i = 0; 
    
        //监听 
    
        if(listen(MainSocket,5) == SOCKET_ERROR) 
    
        { 
    
            printf("监听错误
    "); 
    
        } 
    
        AddLen = sizeof(Client); 
    
     
    
        //连接新的客户 
    
        i = 0; 
    
        for(;;) 
    
        { 
    
            ClientSocket = accept(MainSocket,(SOCKADDR *)&Client,&AddLen); 
    
            if(ClientSocket == SOCKET_ERROR) 
    
            { 
    
                printf("接受客户请求错误!
    "); 
    
            } 
    
            printf("."); 
    
            i ++ ; 
    
            if( i >= 1000) 
    
                i = 0; 
    
            Global[i] = ClientSocket; 
    
     
    
            //对于每一个客户启动不同的线程程进行控制 
    
            //这个地方在使用ClientSocket的时候,要不要保证在某一时刻内只能有一个进程使用?     
    
     
    
       CreateThread(NULL,0,Proxy,(LPVOID)Global[i],0,NULL);
    
     
    
            
    
        } 
    
     
    
        
    
    return 0;
    
    } 
    
    DWORD WINAPI Proxy( LPVOID pSocket) 
    
    { 
    
        SOCKET ClientSocket; 
    
        char  ReceiveBuf[MAXBUFLEN]; 
    
        int  DataLen; 
    
        struct sockaddr_in  ServerAddr; 
    
        SOCKET  ProxySocket; 
    
        int i = 0; 
    
        int time = TIMEWAIT; 
    
     
    
        //得到参数中的端口号信息 
    
        ClientSocket = (SOCKET)pSocket; 
    
    //接受第一次请求信息 
    
        memset(ReceiveBuf,0,MAXBUFLEN); 
    
        DataLen = recv(ClientSocket,ReceiveBuf,MAXBUFLEN,0); 
    
     
    
        if(DataLen == SOCKET_ERROR) 
    
        { 
    
            printf("错误
    "); 
    
            closesocket(ClientSocket); 
    
           return 0;
    
        } 
    
        if(DataLen == 0) 
    
        { 
    
            closesocket(ClientSocket); 
    
           return 0;
    
        }     
    
        //处理请求信息,分离出服务器地址 
    
        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) 
    
        { 
    
            printf("端口创建错误
    "); 
    
            return 0;
    
        } 
    
        if(connect(ProxySocket,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr)) == SOCKET_ERROR) 
    
        { 
    
            //printf("连接服务器错误"); 
    
            goto error; 
    
        } 
    
        //开始进行数据传输处理 
    
        //发送到服务器端 
    
        if(send(ProxySocket,ReceiveBuf,DataLen,0) == SOCKET_ERROR) 
    
        { 
    
            //printf("数据发送错误"); 
    
            goto error; 
    
     
    
        } 
    
            //从服务器端接受数据 
    
        while(DataLen > 0) 
    
        { 
    
            memset(ReceiveBuf,0,MAXBUFLEN); 
    
        
    
            if((DataLen = recv(ProxySocket,ReceiveBuf,MAXBUFLEN,0)) <= 0) 
    
            { 
    
                //    printf("数据接受错误"); 
    
                break; 
    
                
    
            } 
    
                  else 
    
                //发送到客户端 
    
                if(send(ClientSocket,ReceiveBuf,DataLen,0) < 0) 
    
                { 
    
                    //    printf("数据发送错误"); 
    
                        break; 
    
                } 
    
            
    
        } 
    
        
    
    error: 
    
        closesocket(ClientSocket); 
    
        closesocket(ProxySocket); 
    
     
    
        return 0; 
    
     
    
    } 
    
    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); 
    
        //取得/的位置 
    
        printf("%s
    ",FirstLocation);
    
        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) 
    
        { 
    
            printf("服务器名字太长
    "); 
    
            return -1; 
    
        } 
    
        
    
        //得到服务器信息 
    
        //如果地址信息是以IP地址(192.168.0.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("取得主机信息错误
    "); 
    
                printf("%s
    ",ServerName); 
    
                return -1; 
    
           } 
    
            memcpy(&pServer->sin_addr,pHost->h_addr_list[0],sizeof(pServer->sin_addr)); 
    
       } 
    
        
    
       return 0; 
    
    } 
    
     
  • 相关阅读:
    Docker界面化管理
    搭建MQTT服务器(Docker版)
    VS Code Markdown文件实时预览
    Nginx直接处理接口请求,返回相应内容(带html标签)
    Docker(九): 安装MySQL主从复制
    feign的一个注解居然隐藏这么多知识!
    使用Magisk指令修改 ro.debuggable(不刷机)
    【钓鱼可用】文件名反转字符串
    android高级UI之贝塞尔曲线<下>--贝塞尔曲线运用:QQ消息气泡
    英文阅读技巧操练---Article 1:The Product-Minded Software Engineer《一》
  • 原文地址:https://www.cnblogs.com/rinack/p/3195668.html
Copyright © 2011-2022 走看看