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;
}
//此处不可清零,需要解析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;
}
运行结果