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 "S23Bdt3KcyGvyz3kb" //密钥//套接字
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;}//此处不可清零,需要解析JSONprintf("%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;
}
运行结果