• linux c使用socket进行http 通信,并接收任意大小的http响应(二)


    先贴请求头部信息组织代码.

    有同学会疑问http_url.h是干什么用的,我要在这里声明,http_url.h并不是给http_url.c用的,实际上http_url.h声明了http_url.c已经编写好的函数,这样当我们想要在其他c文件使用http_url.c文件的函数的时候就不必将http_url.c文件中的内容整个复制过去,只要包含http_url.h头文件,然后再和http_url.c文件一起编译即可,请搜索linux c 如何同时编译多个文件。

    还有同学会问#ifndef http_url_h #define http_url_h这些东西是什么鬼?这是因为,我们有些时候会不小心将同一个头文件重复包含,像结构体和全局变量的声明一旦重复包含的话,编译器就会报错,我这样做的原因就是为了防止头文件被重复包含

    一、http_url.h

    #ifndef http_url_h
    #define http_url_h

    struct post_data
    {
        char postData[10*1024];

    };
    typedef struct post_data PostData ,*PostData_pointer;

    struct url
    {
        char url[500];
        PostData postData;
    };

    typedef struct url URL,*PURL;
    extern char cookie[100];
    extern int parse_url(char *host,char *path,char *url);
    extern int organize_url(char *url,char *host,char *path);
    extern int http_request(char *request,PURL url);
    extern void num_to_string(char *str,int i);
    extern int Init_URL(PURL Purl,char *url,char *postData);
    #endif

    二、http_url.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    #define ACCEPT_ALL "*/*"
    #define ACCEPT_HTML "text/html"
    #define ACCEPT_JSON "applicaton/json"
    #define CONTENT_NORMAL "application/x-www-form-urlencoded"
    #define CONTENT_MULTI "multipart/form-data"
    #define CRIL " "

    //定义http_url_h,为防止重复定义
    #define http_url_h
    void num_to_string(char *str,int i);

    //定义结构体,用于存储要POST的数据
    struct post_data
    {
        char postData[10*1024];

    };

    typedef struct post_data PostData ,*PostData_pointer;

    //定义结构体,用于存储HTTP通信所需的URL和要POST给URL的数据
    //例如:url->url="http://192.168.6.1",url->postData->postData="name=you&id=123"
    struct url
    {
        char url[500];
        PostData postData;
    };

    typedef struct url URL ,*PURL;

    //全局变量cookie,登录操作之后通过find_cookie可得
    char cookie[100];

    //将URL中的HOST和PATH部分分离
    //参数一:存储HOST的字符串
    //参数二:存储PATH的字符串
    //参数三:将被分解的URL
    //返回值:成功返回1,失败返回0
    int parse_url(char *host,char *path,char *url)
    {
        int i=0,j=0;
        char *flag1,*flag2;
        char temp[200];
        strcpy(temp,url);

        if(url==NULL)
        {
            printf("url is null! ");
            return 0;

        }

        while(temp[i]!='')
        {
            if(temp[i]=='/')
            {
                j++;
            }

            i++;



            if(j==3)
            {
                flag2=&temp[i-1];
                break;

            }

        }

        i=0;
        j=0;
         while(temp[i]!='')
        {
            if(temp[i]=='/')
            {
                j++;
            }

            i++;

            if(j==2)
            {
                flag1=(&temp[i]);
                break;
            }


        }


        if(flag2)
        {
            strcpy(path,flag2);


        }


        if(flag1)
        {
            if(flag2)
            {
                *flag2='';
            }
            strcpy(host,flag1);

            return 1;

        }else
        {
            return 0;

        }


    }

    //将HOST和PATH部分组成一个完整的URL
    //参数一:存储组织完成后的URL
    //参数二:存储HOST的字符串
    //参数三:存储PATH的字符串
    //返回值:成功返回1,失败返回0
    int organize_url(char *url,char *host,char *path)
    {
        char temp[200];
         if(host==NULL)
        {
            printf("host is null! ");
            return 0;

        }

         if(path==NULL)
        {
            printf("path is null! ");
            return 0;

        }

        strcpy(temp,"http://");
        strcat(temp,host);
        strcat(temp,path);

        strcpy(url,temp);

        return 1;

    }

    //根据传入已经初始化的URL结构体,组织HTTP REQUEST头部
    //参数一:存储经组织后的HTTP REQUEST头部的字符串指针
    //参数二:存储有URL和要POST给URL的数据(不一定有)的URL结构体
    //返回值:成功返回1,失败返回0
    int http_request(char *request,PURL url)
    {
        char temp[70000];
        char host[100];
        char path[200];
        char content_length[20];

        if(url==NULL)
        {

            printf("url is null");
            return 0;
        }

        if(strlen(url->postData.postData)>5)//当有数据POST给URL的时候使用POST方法,否则使用GET方法
        {

            strcpy(temp,"POST ");

        }else
        {
            strcpy(temp,"GET ");

        }

        if(parse_url(host,path,url->url))//将完整URL的HOST和PATH部分分解
        {
            if(strlen(path)!=0)
            {

                strcat(temp,path);
                strcat(temp," ");

            }


        }else
        {

            printf("url not exsist! ");
            return 0;

        }

        strcat(temp,"HTTP/1.0");
        strcat(temp,CRIL);
        strcat(temp,"Host: ");
        strcat(temp,host);
        strcat(temp,CRIL);

        if(strlen(cookie)>10)
        {
            strcat(temp,"Cookie: ");
            strcat(temp,cookie);
            strcat(temp,CRIL);

        }


        strcat(temp,"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        strcat(temp,CRIL);

        strcat(temp,"Connection: close");//使用close的原因是,在使用socket进行通信的时候,选择keep-alive响应特别慢
        strcat(temp,CRIL);

        strcat(temp,"Upgrade-Insecure-Requests: 1");
        strcat(temp,CRIL);

        strcat(temp,"Accept-Encoding: gzip, deflate");
        strcat(temp,CRIL);

        strcat(temp,"Accept-Language: en-US,en;q=0.5");
        strcat(temp,CRIL);

        if(strlen(url->postData.postData)>5)//当有数据POST给URL的时候,带上POST的数据
        {
            strcat(temp,"Content-Type: ");
           
            if(strstr(url->postData.postData,"------"))//检查是不是multipart date 数据
            {
                strcat(temp,CONTENT_MULTI);//注意:CONTENT_NORMAL和CONTENT_MULTI不是变量,是宏定义!!!!好吧,原本是小写的,现在我已经改了
                strcat(temp,"; boundary=");
                strcat(temp,"------WebKitFormBoundaryaoOeFzIPZu3yeBWJ ");
            }else
            {
                strcat(temp,CONTENT_NORMAL);
                strcat(temp,CRIL);

            }

            strcat(temp,"Content-Length: ");
            num_to_string(content_length,strlen(url->postData.postData));
            strcat(temp,content_length);
            strcat(temp,CRIL);
            strcat(temp,CRIL);
            strcat(temp,url->postData.postData);


        }else
        {
            strcat(temp,CRIL);
            
        }

        printf("%s ",temp);

        strcpy(request,temp);
        return 1;
    }

    //URL结构体初始化函数
    //参数一:指向要被初始化的URL结构体的指针
    //参数二:完整的URL,如http://192.168.6.1/overview
    //参数三:要POST给URL的数据,可为NULL.当为NULL的时候,将初始化后的URL结构体给int http_request(char *request,PURL url)函数组织头部,会自动设置POST和GET方法
    int Init_URL(PURL Purl,char *url,char *postData)
    {
        if(url!=NULL)
        {
            strcpy(Purl->url,url);
        }
        else
        {
            printf("url is null! ");
            return 0;
        }

        if(postData!=NULL)
        {
            strcpy(Purl->postData.postData,postData);
        }else
        {
            strcpy(Purl->postData.postData,"");
        }

        return 1;
    }
    整个过程其实就是一顿字符串的组织和解析,最终的目的是为了组织出如下的头部,看起来很长,但是实际上没有什么技术含量。

    当组织成的头部大概是这个样子,在URL结构体postDate的数据为空的时候

    当在URL结构体postDate的数据不为空的时候,大概是这样

  • 相关阅读:
    Scrapy爬虫的基本使用
    scrapy 常见问题
    yield 关键字的使用
    Scrapy 爬虫框架
    股票数据爬虫
    为什么CNN需要固定输入图像的尺寸
    实战 7 淘宝商品信息定向爬虫
    正则表达式
    w​x​F​o​r​m​B​u​i​l​d​e​r​初​体​验
    wxwidget wxpython 可视化开发工具
  • 原文地址:https://www.cnblogs.com/thegodofthunder/p/7216275.html
Copyright © 2020-2023  润新知