使用socket进行http通信的时候,浏览器返回的响应经常不是固定长度的,有时候很大,有些时候又非常小,十分讨厌。如果仅仅只是为了接收一小段信息,设置一个十分大的缓存,这样又会十分浪费。而且经常更改缓存大小的话,也不太好。

为了能够接收任意大小的响应,我程序的流程大概是这样子的:

(1)将SOCKET接收的信息保存到一个动态分配内存的链表里。链表每个节点存储有固定字节大小的HTTP响应,每当一个节点存储满,就继续添加一个新的节点继续缓存;

(2)接收信息结束后,将存储在链表当中的HTTP响应全部取出,合并,放到一个统一的动态内训空间中。

与链表有关的函数如下:

(1)data2.h

//声明在其他程序当中可能用到data2.c的函数
#ifndef textbuffer_h
#define textbuffer_h
struct textbuffer
{
    char data[52224];
    struct textbuffer *next;

};

typedef struct textbuffer TEXTBUFFER,*PBUFFER;

extern PBUFFER create_EmptyBufferLink();
extern PBUFFER create_EmptyBuffer();
extern PBUFFER append_Buffer_Node(PBUFFER header);
extern int free_Buffer_Link(PBUFFER header);
extern unsigned long count_Buffer_Node(PBUFFER header);
extern char* get_All_Buffer(PBUFFER header);
#endif // textbuffer_h

(2)data2.c

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

//定义节点结构体用于缓存HTTP响应
//textbuffer_h表示已经定义了textbuffer结构体(防止重复定义)
#define textbuffer_h
struct textbuffer
{
    char data[52224];
    struct textbuffer *next;

};
typedef struct textbuffer TEXTBUFFER,*PBUFFER;

//创建头节点
//返回值:成功返回指向动态内存指针,失败返回NULL
//注:1)创建头结点之后,注意检查头结点是否为空再使用;2)头结点的下一个结点才开始存储内容
PBUFFER create_EmptyBufferLink()
{

PBUFFER header;
    header=(PBUFFER)malloc(sizeof(TEXTBUFFER));

if(header!=NULL)
    {
        memset(header,0,sizeof(TEXTBUFFER));
        header->next=NULL;
    }

return header;

}

//创建一个空的节点
//如果动态分配成功,局部变量node当中存有的是动态内存的地址,但是为防止极端情况(有人故意将可分配的动态空间占用完),还是改了一下代码
//返回值:成功返回指向动态内存指针,失败返回NULL
PBUFFER create_EmptyBuffer()
{
    PBUFFER node;
    if(NULL!=(node=(PBUFFER)malloc(sizeof(TEXTBUFFER))))
    {
        memset(node,0,sizeof(TEXTBUFFER));
        node->next=NULL;
    }
    
    return node;

}

//向链表尾部添加节点,返回新添加节点的指针,节点的内容可以通过返回的节点指针向其添加
//注:注意检查新分配的节点是否为NULL
PBUFFER append_Buffer_Node(PBUFFER header)
{

PBUFFER newNode,nowNode;
    if(header==NULL)
    {
        printf("header is null!\n");
        return 0;
    }
    newNode=create_EmptyBuffer();

nowNode=header;

while(nowNode->next!=NULL)
    {
        nowNode=nowNode->next;

}

nowNode->next=newNode;

return newNode;
}

//清空除了头结点之外其他的所有节点
int empty_Buffer_Node(PBUFFER header)
{
    PBUFFER nowNode,freeNode;

if(header==NULL)
    {
        printf("header is null!\n");
        return 0;
    }

nowNode=header;
    nowNode=nowNode->next;
    while(nowNode!=NULL)
    {
        freeNode=nowNode;
        nowNode=nowNode->next;
        free(freeNode);
    }

header->next=NULL;

return 1;

}

//清空包括头结点在内的所有节点
int free_Buffer_Link(PBUFFER header)
{

if(header==NULL)
    {
        printf("header is null!\n");
        return 0;
    }

empty_Buffer_Node(header);
    free(header);
    header=NULL;
    return 1;
}

//计算BUFFER链表一共存储了多少字节的响应,并且返回最终结果
unsigned long count_Buffer_Node(PBUFFER header)
{
    PBUFFER nowNode;
    unsigned long i=0;
    if(header==NULL)
    {
        printf("header is null!\n");
        return 0;
    }

nowNode=header;

while(nowNode->next!=NULL)
    {
        nowNode=nowNode->next;
        i+=strlen(nowNode->data);
    }

return i;
}

//将整个BUFFER链表的内容提取出来,并存储到动态内存之中,返回动态内存的指针
//注:1)执行到此步,若是不再使用BUFFER链表,应用int free_Buffer_Link(PBUFFER header)释放链表
//2)返回的动态内存指针,若是不再使用动态内存里面的内容应通过free将其释放
char* get_All_Buffer(PBUFFER header)
{
    unsigned long i;
    PBUFFER nowNode;
    char *result;
    if(header==NULL)
    {
        printf("header is null!\n");
        return NULL;
    }
    i=count_Buffer_Node(header);
    result=(char*)malloc((i+100)*sizeof(char));
    memset(result,'\0',i*sizeof(char));

nowNode=header;

while(nowNode->next!=NULL)
    {
        nowNode=nowNode->next;
        strcat(result,nowNode->data);
    }
    printf("\nresult is:%s\n",result);
    return result;

}

当然,我只是考虑到功能的实现,并未考虑到效率的问题。

linux c使用socket进行http 通信,并接收任意大小的http响应(三)的更多相关文章

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

    终于说到SOCKET 这里了.SOCKET进行http通信的实际就是利用socket将http请求信息发送给http服务器,然后再利用socket接收http响应. 由于本文与之通信的服务器是ip已知 ...

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

    先贴请求头部信息组织代码. 有同学会疑问http_url.h是干什么用的,我要在这里声明,http_url.h并不是给http_url.c用的,实际上http_url.h声明了http_url.c已经 ...

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

    如何进行http通信呢?我们打开任意一个浏览器,按F12,再选择网络,然后打开任意一个网站,我们就可以看到浏览器和网站通信的过程 如下图: 然后,我们任意点击一条记录,可以看到 然后,查找http协议 ...

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

    http.c data2.c http_url.c http.h data2.h http_url.h主要实现的功能是通过URL结构体来实现HTTP通信,你可以把这三个文件独立出来,作为HTTP通信模 ...

  5. c++ 网络编程(一)TCP/UDP windows/linux 下入门级socket通信 客户端与服务端交互代码

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/9601511.html c++ 网络编程(一)TCP/UDP  入门级客户端与服务端交互代码 网 ...

  6. 基于ARM9和嵌入式Linux系统的多功能综合通信控制系统的框架

    基于ARM9硬件平台和嵌入式Linux系统的多功能综合通信控制系统的框架设计及各模块的功能.系统采用符合POSIX.1标准的C语言编写,实现了对下位机传送数据帧的采集.分析和存储,并能根据上位机的配置 ...

  7. LINUX 下 ipv6 socket 编程

    大家都知道,随着互联网上主机数量的增多,现有的32位IP地址已经不够用了,所以推出了下一代IP地址IPv6,写网络程序的要稍微改变一下现有的网络程序适应IPv6网络是相当容易的事.对于我们来说就是IP ...

  8. linux各种IPC机制(进程通信)

    linux各种IPC机制 (2011-07-08 16:58:35)      原文地址:linux各种IPC机制(转)作者:jianpengliu 原帖发表在IBM的developerworks网站 ...

  9. Linux学习之socket编程(二)

    Linux学习之socket编程(二) 1.C/S模型——UDP UDP处理模型 由于UDP不需要维护连接,程序逻辑简单了很多,但是UDP协议是不可靠的,实际上有很多保证通讯可靠性的机制需要在应用层实 ...

随机推荐

  1. c# Resolve SQlite Concurrency Exception Problem (Using Read-Write Lock)

    This article describes the c# example to solve the problem of SQlite concurrent exception method. To ...

  2. 运行pytorch代码遇到的error解决办法

    1.no CUDA-capable device is detected 首先考虑的是cuda的驱动问题,查看gpu显示是否正常,然后更新最新的cuda驱动: 第二个考虑的是cuda设备的默认参数是否 ...

  3. 213. House Robber II(动态规划)

    You are a professional robber planning to rob houses along a street. Each house has a certain amount ...

  4. python 用lambda表达式代替简单的函数, 匿名函数

    lambda 函数是一种快速定义单行的最小函数,可以用在任何需要函数的地方 格式: lambda 参数列表:return [表达式] 变量 由于lambda返回的是函数对象(构建的是一个函数对象),所 ...

  5. Centos 编译 安装 criu

    下载依赖库 sudo yum install protobuf protobuf-c protobuf-c-devel protobuf-compiler protobuf-devel protobu ...

  6. mysql插入数据报错1366

    数据表插入中文数据报错 Warning Code : 1366 Incorrect string value: '\xE5\x9C\xA8' for column 'name' at row 1 原因 ...

  7. LATCH_VARIANT = Magna compile

    after: LATCH_VARIANT = Magna in m_project_cfg.mak of PG_.. 1. first error: SED   tmp__.dep/bin/sh: / ...

  8. CentOS 6.5优化开机启动服务

    使用chkconfig命令列举出所有服务,配合管道筛选出开机默认启动的服务,再去掉level0(关机).level4(无意义)和level6(重启)的显示,使结果更直观. chkconfig | gr ...

  9. layer(jQuery弹出层插件)

    弹窗alert:默认确定按钮+右上角关闭 top.layer.alert("请选择要删除的记录!",{shade: 0.3,offset:'250px'}); 弹窗alert:默认 ...

  10. [译]课程 1: 使用 Quartz

    译者注: 原文在这 Lesson 1: Using Quartz 在你使用调度器之前, 你需要先实例化(能猜到是谁么?). 要实例化, 请使用 ISchedulerFactory 的实现. 译者注: ...