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

使用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;

}

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

时间: 2024-08-01 21:13:51

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

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

终于说到SOCKET 这里了.SOCKET进行http通信的实际就是利用socket将http请求信息发送给http服务器,然后再利用socket接收http响应. 由于本文与之通信的服务器是ip已知的,所以为了能够将能够和互联网网站进行http通信还要另外像办法. 代码如下: (1)http.h //http.c当中可能被其他程序锁用到的函数的声明#include "http_url.h"#ifndef http_h#define http_htypedef struct socka

C语言 linux环境基于socket的简易即时通信程序

转载请注明出处:http://www.cnblogs.com/kevince/p/3891033.html   By Kevince 最近在看linux网络编程相关,现学现卖,就写了一个简易的C/S即时通信程序,代码如下: head.h 1 /*头文件,client和server编译时都需要使用*/ 2 #include <unistd.h> 3 #include <stdio.h> 4 #include <sys/types.h> 5 #include <sys

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

linux各种IPC机制 (2011-07-08 16:58:35)     原文地址:linux各种IPC机制(转)作者:jianpengliu 原帖发表在IBM的developerworks网站上,是一个系列的文章,作者郑彦兴,通过讲解和例子演示了Linux中几种IPC的使用方式,我觉得很好,在这里做一个保留,能看完的话Linux IPC的基础是没有问题的了.一)Linux环境进程间通信(一)管道及有名管道http://www.ibm.com/developerworks/cn/linux/

基于Linux C的socket抓包程序和Package分析 (一)

 测试运行平台:CentOS 6.5发行版,内核版本3.11 1. Linux抓包源程序 在OSI七层模型中,网卡工作在物理层和数据链路层的MAC子层. 进行网络通信时,源主机通过socket(或其它)应用程序产生IP报文,经过各个OSI层层封装,数据包以Ethernet帧的形式进入物理层.Ethernet帧包含源主机地址.IP报文.目标地址(IP地址.端口号或映射的6字节MAC地址)和需要传送到目标主机的其它信息. 目标的MAC地址是哪里来的呢?这牵扯到一个ARP协议(介乎于网络层和数据链

Linux系统编程札记:进程通信(一) &nbsp; &nbsp;

进程简单来讲就是一个程序的一次执行,这里说的进程一般都指的是运行在用户态的进程,而处于用户态的不同进程之间是彼此相互隔离的,它们必须通过某种方式来进行通信,具体理由如下: (1)数据传输:有时候一个进程需要将它的数据发送给另一个进程. (2)资源共享:有时候多个进程之间需要共享同样的资源. (3)通知事件:有时候一个进程需要向另一个或一组进程发送消息,通知它们发生了某个事件. (4)进程控制:有些进程希望能够完全控制另一个进程的执行,此时控制进程希望能够拦截另一进程的所有操作,并能够及时知道它的

Linux下的socket网络编程

linux 网络编程是通过socket(套接字)接口实现,Socket是一种文件描述符,socket起源于UNIX,在Unix一切皆文件哲学的思想下,socket是一种"打开-读/写-关闭"模式的实现,服务器和客户端各自维护一个"文件",在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件. socket 类型 常见的socket有3种类型如下.     (1)流式socket(SOCK_STREAM )     流式套接字提供可靠

LINUX 下 ipv6 socket 编程

大家都知道,随着互联网上主机数量的增多,现有的32位IP地址已经不够用了,所以推出了下一代IP地址IPv6,写网络程序的要稍微改变一下现有的网络程序适应IPv6网络是相当容易的事.对于我们来说就是IP地址变化了,所以程序里在用到IP地址的地方做相应的改变就可以了. 记住:主要是改变程序里设置IP地址和端口等部分的代码. 服务器端源代码如下:/***********************/#include <stdio.h>#include <stdlib.h>#include &

Flex Socket与Java通信实例说明(转)

Flex Socket与Java通信实例说明(转) 这两天一直在flex的Socket ,现在终于懂了很多.由浅到深一步一步深入.慢慢体会实例,虽然实例都是在网上找的,但也经过了我的测试.我比较喜欢注释,也注释了很多. 跟着走你就会懂.. Flex端 和 Java端, 先运行Java端启动服务.然后在测试Flex. 实例一: Flex端: <?xml version="1.0" encoding="utf-8"?> <mx:TitleWindow

Windows 和 Linux下使用socket下载网页页面内容(可设置接收/发送超时)的代码

主要难点在于设置recv()与send()的超时时间,具体要注意的事项,请看代码注释部分,下面是代码: [cpp] view plaincopyprint? #include <stdio.h> #include <sys/types.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <string.h> #ifdef _WIN32   ///