http与cJSON练习

http与cJSON练习

/****************************************************************************************************
*                                       weather_test.c
*               练习tcp连接,与http协议,调用服务器接口,实现获取特定城市的天气信息,并用cJSON解析
*               需要添加cJSON.c和cJSON.h
*               下载地址https://github.com/DaveGamble/cJSON
****************************************************************************************************/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdbool.h>
#include <netdb.h>

#include "cJSON.h"

#define PORT 80                                //http协议默认80端口
#define DOMAIN_NAME "api.seniverse.com"            //天气接口API,此处使用的是心知天气
#define CITY        "Jieyang"                      //城市
#define KEY      "you key"            //密钥

//套接字
int tcp_socket = 0;

//接收缓冲区
char recv_buf[1024] = {0};

/**
 *函数名称	connect_init
 *函数功能	初始化tcp连接
 *函数参数	NONE
 *返回结果	布尔型
 *注意事项	NONE
 */
bool connect_init()
{  
    //创建TCP套接字
	tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
	if (tcp_socket == -1)
	{
		fprintf(stderr, "tcp socket error,errno:%d,%s\n",
                errno,strerror(errno)
                );
		return false;
	}

    /*****************************相关结构体*******************************/
        //  struct hostent {
        //        char  *h_name;            /* official name of host */
        //        char **h_aliases;         /* alias list */
        //        int    h_addrtype;        /* host address type */
        //        int    h_length;          /* length of address */
        //        char **h_addr_list;       /* list of addresses */
        //    }
    /********************************************************************/
    //解析域名
    struct hostent* ipaddr=gethostbyname(DOMAIN_NAME);

    struct in_addr *addr = (struct in_addr *)ipaddr->h_addr_list[0];
    printf("%s\n", inet_ntoa(*addr));

    //初始化结构体
    struct sockaddr_in weather_addr;
    //协议
    weather_addr.sin_family         = AF_INET;
    //端口
    weather_addr.sin_port          = htons(PORT);
    //服务器地址
    weather_addr.sin_addr. s_addr   = inet_addr(    inet_ntoa(*addr)    );

    //开始连接
    int ret = connect(tcp_socket,(struct sockaddr*)&weather_addr,sizeof(weather_addr));
    if(-1 == ret){
        fprintf(stderr, "connect error,errno:%d,%s\n",
                errno,strerror(errno)
                );
		return false;
    }
    printf("连接成功\n");
    return true;
}



/**
 *函数名称	request_http
 *函数功能	http请求
 *函数参数	NONE
 *返回结果	NONE
 *注意事项	NONE
 */
void request_http()
{
    //请求缓冲区
    char req_buf[1024] = {0};
    //向缓冲区写入请求
    sprintf(req_buf,"GET https://api.seniverse.com/v3/weather/now.json?key=%s&location=%s&language=zh-Hans&unit=c "  //空格不能省略
            "HTTP/1.1"
            "\r\n"
            "HOST:%s\r\n"
            "\r\n"
            ,KEY,CITY,DOMAIN_NAME
            );

    //循环请求直到成功接收信息
    while(1){

        //发送请求
        if( -1 == send(tcp_socket,req_buf,sizeof(req_buf),0) ){
            fprintf(stderr,"send error,errno[%d]:%s\n",
                    errno,strerror(errno)
                    );
            continue;
        }
        printf("请求发送成功\n");

        //第一次接收响应
        if( -1 == recv(tcp_socket,recv_buf,sizeof(recv_buf),0)  ){

            fprintf(stderr,"recv error,errno[%d]:%s\n",
                    errno,strerror(errno)
                    );
            continue;
        }

        printf("%s\n",recv_buf);
        //清零
        bzero(recv_buf,1024);
        printf("*******************************************\n");
        //第二次接收响应
        if(-1 == recv(tcp_socket,recv_buf,sizeof(recv_buf),0)){

            fprintf(stderr,"recv error,errno[%d]:%s\n",
                    errno,strerror(errno)
                    );
            continue;
        }
        //此处不可清零,需要解析JSON
        printf("%s\n",recv_buf);
        break;
    }
    
}

/**
 *函数名称	weather_JSON
 *函数功能	解析JSON
 *函数参数	NONE
 *返回结果	NONE
 *注意事项	NONE
 */
void weather_JSON()
{
    //将字符串转换为josn格式
    cJSON* weather = cJSON_Parse(recv_buf);
    //解析
    cJSON* results  = cJSON_GetObjectItem(weather, "results");
    cJSON* array    = cJSON_GetArrayItem(results,0);

    cJSON* location = cJSON_GetObjectItem(array,"location");

    cJSON* name     = cJSON_GetObjectItem(location,"name");
    cJSON* country  = cJSON_GetObjectItem(location,"country");

    cJSON* now      = cJSON_GetObjectItem(array,"now");
    cJSON* text     = cJSON_GetObjectItem(now,"text");

    cJSON* last_update = cJSON_GetObjectItem(array,"last_update");

    /*****************************相关结构体*******************************/
        // typedef struct cJSON {
        //     struct cJSON *next,*prev;	
        //     struct cJSON *child;		

        //     int type;					

        //     char *valuestring;			
        //     int valueint;				
        //     double valuedouble;			

        //     char *string;				
        // } cJSON;
    /********************************************************************/
    printf("当前城市%s-%s,该城市天气为%s   %s\n",   country->valuestring,
                                                    name->valuestring,
                                                    text->valuestring,
                                                    last_update->valuestring
                                                    );

}


int main()
{
    connect_init();
    request_http();
    weather_JSON();
    return 0;
}

运行结果
image

posted @ 2024-06-11 21:48  歪币八卜  阅读(63)  评论(2)    收藏  举报