终于说到SOCKET 这里了。SOCKET进行http通信的实际就是利用socket将http请求信息发送给http服务器,然后再利用socket接收http响应。

由于本文与之通信的服务器是ip已知的,所以为了能够将能够和互联网网站进行http通信还要另外像办法。

代码如下:

(1)http.h

//http.c当中可能被其他程序锁用到的函数的声明
#include "http_url.h"
#ifndef http_h
#define http_h
typedef struct sockaddr_in ip;
typedef struct sockaddr *IP;
extern char cookie[200];
extern int create_socket();
extern void init_ip(ip *httpip,char *Ip,int port);
extern int Bind(int socket,ip *httpip);
extern int get_other_socket(int socket);
extern int Connect(int socket,ip* httpip);
extern int Send(int socket,char *Data);
extern char* Read(int socket);
extern int http_perform_url(PURL url,char **Buffer);
extern int find_cookie(char *Cookie,char *httpBuffer);
extern void randomCode(char *result);
extern void Set_Cookie(char *cookie_);
extern void httpBuffer_free(char **respond);
#endif // http_h

(2)http.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include "http_url.h"//加入http_hrl模块
#include "data2.h"//加入data2模块,data2模块用于存储和处理HTTP响应
#define SETCOOKIE "Set-Cookie: "
#define SENDSIZE 4096//每次发送数据的大小,注:未使用

#define http_h
//注意:本文件所有定义函数只适合HTTP通信----排除某些例外函数
//用sockaddr_in、struct sockaddr *结构体存储IP
typedef struct sockaddr_in ip;
typedef struct sockaddr *IP;

//全局变量cookie,注:目前仅支持一个cookie
char cookie[200];

int is_respond_ok(char *httpBuffer);

//自定义创建socket的函数
//返回值:成功返回socket嵌套字,失败返回-1
int create_socket()
{
    int temp;
    temp=socket(AF_INET,SOCK_STREAM,0);
    return temp;

}

//自定义初始化ip结构体的函数
//参数一:指向将被初始化的ip结构体的指针
//参数二:具体的IP,例如:192.167.6.5
//参数三:通信端口,HTTP通信应传入80
void init_ip(ip *httpip,char *Ip,int port)
{
    memset(httpip,0,sizeof(*httpip));
    httpip->sin_family=AF_INET;
    httpip->sin_addr.s_addr=inet_addr(Ip);
    httpip->sin_port=htons(port);
}

//自定义将socket和IP绑定的函数
//参数一:socket嵌套字
//参数二:已经指向已经初始化了的ip结构体的指针
//返回值:成功则返回0, 失败返回-1, 错误原因存于errno 中
int Bind(int socket,ip *httpip)
{
    int ret;
    ret=bind(socket,(IP)httpip,sizeof(httpip));
    return ret;
}

//自定义通过accept阻塞等待其他socket对其进行连接的函数
//参数一:要被阻塞的socket嵌套字
//返回值:有其他socket连接到被阻塞的socket则返回和被阻塞的socket进行通信的另一socket嵌套字
int get_other_socket(int socket)
{
    ip otherip;
    int temp;
    socklen_t length;
    length=sizeof(otherip);
    temp=accept(socket,(IP)&otherip,&length);
    return temp;

}

//自定义connect函数
//参数一:客户端自己的socket
//参数二:指向将被连接的IP结构体的指针
//返回值:成功则返回0, 失败返回-1, 错误原因存于errno 中
int Connect(int socket,ip* httpip)
{
    int flag;
    flag=connect(socket,(IP)httpip,sizeof(*httpip));
    return flag;
}

//自定义Send函数
//参数一:自己程序的socket
//参数二:将要发送的数据
//返回值:大于或等于零表示发送了部分或是全部的数据,失败返回-1, 错误原因存于errno 中
//待修改:由于write函数一次可能写不完,所以可能需要修改函数进行多次发送???????????????????如果我没有修改,请后来的勇者继续修改
int Send(int socket,char *Data)
{
    int ret=1;
/*    int sendLength=0,dataLength=0;

while(ret!=0)
    {}
*/

ret=write(socket,Data,strlen(Data));
    return ret;
}

//自定义Read函数
//参数一:自己程序的socket
//返回值:成功返回指向存储有相应内容的动态内存的指针,失败返回NULL
//注意:1)返回的动态内存指针在不使用的时候应该通过free释放;2)如果不是真的有问题,请不要动,如果读取数据出现问题,请优先检查data2.c中的函数
char* Read(int socket)
{
    int length=0,return_length;
    char buffer[1024];
    char *Data;
    PBUFFER header,nowBuffer;//nowBuffer指向正在使用的BUFFER节点

if(NULL!=(header=create_EmptyBufferLink()))//创建BUFFER表头
    {
        if(NULL==(nowBuffer=append_Buffer_Node(header)))//创建第一个存储响应的BUFFER节点
        {
            printf("\nappend_Buffer_Node() fail in http.c Read()\n");//节点添加失败直接返回
            free_Buffer_Link(header);
            return NULL;
        }

}else
    {
        printf("\ncreate_EmptyBufferLink() fail in http.c Read()\n");//头结点创建失败直接返回
        return NULL;
    }

//每次读取1024个节点存储到buffer中,然后再通过strncpy复制到BUFFER节点当中
    while((return_length=read(socket,buffer,1024))>0)
    {
        if(return_length==-1)
        {
            printf("\nreceive wrong!\n");
            free_Buffer_Link(header);
            header=NULL;
            return NULL;
        }else
        {

if(length>=50176)//如果节点已经快要存满,则新建节点,将相应内容存到新建立的节点当中
            {
                nowBuffer->data[length]='\0';
                if(NULL==(nowBuffer=append_Buffer_Node(header)))
                {
                    printf("\nappend_Buffer_Node() fail in http.c Read()\n");//节点添加失败直接返回
                    free_Buffer_Link(header);
                    return NULL;
                }
                length=0;
                strncpy(nowBuffer->data+length,buffer,return_length);
                length+=return_length;
            }
            else
            {
                strncpy(nowBuffer->data+length,buffer,return_length);
                length+=return_length;
            }
        }

}

nowBuffer->data[length]='\0';
    Data=get_All_Buffer(header);//将BUFFER链表中的内容取出,存储到动态内存当中

//释放BUFFER链表
     if(header!=NULL)
    {
        free_Buffer_Link(header);
        header=NULL;
    }

if(length==0)
    {
       printf("no date receive!\n");
        return NULL;
    }

return Data;//返回指向存储有响应内容的动态内存的指针(可能为空)
}

//进行HTTP通信
//参数一:要进行HTTP通信的IP,如192.168.6.1
//参数二:发送给HTTP服务端的数据
//参数三:指向存储HTTP响应内容指针的变量的指针,如不明白,可参考动态内存在函数间的传递
//返回值:成功返回1,失败返回0
//注意:动态内存必须释放
int http_perform(char *Ip,char *DataSend,char **buffer)
{

int client_socket_word;
    ip httpip;

if(-1==(client_socket_word=create_socket()))
    {
        perror("http.c create_socket() fail");
        return 0;
    }

init_ip(&httpip,Ip,80);

if(-1==Connect(client_socket_word,&httpip))
    {
        perror("http.c Connect() fail");
        return 0;
    }

if(-1==Send(client_socket_word,DataSend))
    {
        perror("http.c Send() fail");
        return 0;
    }

*buffer=Read(client_socket_word);

if(NULL==buffer)
    {
        perror("http.c Read() fail");
        return 0;
    }

if(-1!=client_socket_word)
    {
        close(client_socket_word);
        return 1;
    }

return 0;
}

//通过结构体URL进行HTTP通信
//参数一:存储有通信信息的结构体
//参数二:指向存储HTTP响应的动态指针的地址,使用完之后必须释放,使用之前必须检查BUFFER是否为NULL(即使is_respond_ok()失败,动态内存中依旧可能存储有响应失败的信息)
//返回值:成功返回1,失败返回0
//注意:无论成功或是失败,动态内存真的必须释放!!!
int http_perform_url(PURL url,char **Buffer)
{
    char host[100];
    char path[500];
    char request[10*1024];//差点忘了你

memset(request,'\0',10*1024*sizeof(char));

if(1==http_request(request,url))
    {
        if(1==parse_url(host,path,url->url))
        {

if(1==http_perform(host,request,Buffer))
            {
                if(NULL!=Buffer)
                {
                    if(1==is_respond_ok(*Buffer))
                    {
                        return 1;
                    }
                }
            }

}
    }

return 0;
}

//截取两个指针之间的字符串
//参数一:字符串开始的指针
//参数二:字符串结束的指针
//返回值:成功返回1,失败返回0
int str_between(char* result,char *pStart,char *pEnd)
{
    char *result_,*pStart_;
    result_=result;
    pStart_=pStart;

if((pStart)&&(pEnd)&&(pEnd>pStart))
    {
        while((pStart_)!=pEnd)
        {
            *(result_)=*(pStart_);
            pStart_++;
            result_++;

}
    }else
    {
        return 0;
    }
    *(result_)='\0';
    return 1;
}

//从HTTP响应当中寻找COOKIE
//参数一:存储COOKIE字符串的指针
//参数二:存储有COOKIE的HTTPBUFFER
int find_cookie(char *Cookie,char *httpBuffer)
{
    char *pStart,*pEnd,*temp;
    if((strstr(httpBuffer,SETCOOKIE)!=NULL))
    {
        temp=strstr(httpBuffer,SETCOOKIE);
        pStart=temp+sizeof(SETCOOKIE);
        pStart--;
    }

if((temp=strstr(httpBuffer,"; path"))!=NULL)
    {
        pEnd=temp;
    }

if(!((pStart)&&(pEnd)))
    {
        return 0;
    }

if(str_between(Cookie,pStart,pEnd))
    {
        printf("%s\n",Cookie);
        return 1;
    }
    else
    {
        return 0;
    }

}

//当想要自己设置cookie,可以通过这个函数将自定义的cookie复制到全局变量当中
//参数一:cookie字符串,如:“synsnd=hdh38rhy3gdyug873gdyguwsgdipo39yrdh”
void Set_Cookie(char *cookie_)
{
    if(cookie_)
    {
        strcpy(cookie,cookie_);
    }

}

//通过检查HTTPBUFFER当中是否有“302 Found”和“200 OK”判断响应是否成功
//参数1:HTTPBUFFER
//返回值:成功返回1,失败返回0
int is_respond_ok(char *httpBuffer)
{
    if((strstr(httpBuffer,"302 Found"))||(strstr(httpBuffer,"200 OK")))
    {
        printf("Respond ok!\n");
        return 1;
    }
    else
    {
        printf("Respond wrong!\n");
        return 0;

}
}

//产生长度大概为16-19的随机数字字符串
//参数一:用于存储随机数字字符串的字符串指针
//待修改:我没有设定返回值和纠错机制,只要用足够大的字符串去接受的话,一般不会出错
void randomCode(char *result)
{
    int i;
    char temp1[20],temp2[20];
    srand((unsigned int)time(NULL));
    i=rand();
    num_to_string(temp1,i);
    i=rand();
    num_to_string(temp2,i);

strcpy(result,temp1);
    strcat(result,temp2);
}

//当HTTP响应不为空,用以释放存储响应的动态内存
void httpBuffer_free(char **respond)
{
    if(*respond!=NULL)
    {
        free(*respond);
        *respond=NULL;//应该为*respond=NULL而不是respond=NULL,改变的是respond中存储的指针
    }
}

下一篇放使用例子。

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

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

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

  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. 56.关于vue项目的seo问题

    不可否定的是,vue现在火.但是在实际项目中,特别是像一下交互网站,我们不可避免会考虑到的是seo问题,这直接关系到我们网站的排名,很多人说用vue搭建的网站不能做优化,那我们真的要放弃vue,放弃前 ...

  2. CentOS 7 DR模式LVS搭建

    调度器LB : 192.168.94.11 真实web服务器1 : 192.168.94.22 真实web服务器2 : 192.168.94.33 VIP : 192.168.94.111 脚本如下 ...

  3. 【Checkio Exercise】Three Point Circle

    计算三角形外接圆的函数: Three Point Circle If we want to build new silos, then we need to make more formal and ...

  4. JavaScript 字典

    JavaScript 字典 字典以 key value 形式出现 使用: a = {'k1':'v1,''k2':'v2'} 获取值: a['k1'] 获取值:v1

  5. MI200e电力线通讯

    最近做课设,选了电力线通讯这种途径,经过百度google等一番查询,最终敲定了mi200e这块国产芯片. 课设要求就是双机通讯,互传传感器信息以及模拟一个时钟 然后淘宝买了拆机的成品,我拿回来把mcu ...

  6. final修饰符与多态

    知识点一.final 最终的可以修饰属性.方法.类1.final修饰的属性,表示常量,初始化以后值不能改变.final修饰引用数据类型的变量,引用地址不能改变.2.final修饰类,不能被继承.比如: ...

  7. hadoop MR的一些文件归属(包括临时文件存储情况)

    https://blog.csdn.net/bxyz1203/article/details/8057810

  8. Bootstrap3基础 page-header 标题下加分割线

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  9. 【2.0】SpringBoot连接MySql 8.0的url设置

    jdbc:mysql://localhost:3306/enterprise?useUnicode=true&amp&useSSL=false&amp&characte ...

  10. Windows下nginx+tomcat实现简单的负载均衡

    Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请 ...