基于HTTP传输协议、cJSON库的网络天气获取程序
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include "cJSON.h" //cJSON头文件
#define SERV_PORT 80 //http端口号
#define CLI_PORT 8888 //本地端口号
#define CLI_IP "172.23.60.138" //本地IP
#define DOMAIN_NAME "api.seniverse.com" //域名
#define KEY "SzIYujfNSBeee1MPr" //密钥
#define LOCATION "guangzhou" //地区
#define LANGUAGE "zh-Hans" //语言
#define MAX_IP_LEN 16 //IP长度
//常用数据结构体
typedef struct client_information
{
char ip[MAX_IP_LEN]; //域名对应IP
int sock_fd; //套接字
struct cJSON *root; //cJSON格式的根对象指针
}client_inf, *client_inf_p;
// JSON结构体
// typedef struct cJSON
// {
// struct cJSON *next,*prev;
// struct cJSON *child; //树状结构
// int type; //值的类型
// char *valuestring; //字符串类型的值
// int valueint; //整型类型的值
// double valuedouble; //浮点类型的值
// char *string; //"name"
// } cJSON;
int Client_Link(client_inf_p cli_inf); //客户端连接服务器函数
void Get_Weather(client_inf_p cli_inf); //从服务器获取天气信息并转换成cJSON格式
void Parse_cJSON(client_inf_p cli_inf); //解析cJSON格式信息
int main(int argc, char *argv[])
{
//定义并为常用信息结构体申请堆空间
client_inf_p cli_inf = (client_inf_p)malloc(sizeof(client_inf));
if (cli_inf == NULL)
{
fprintf(stderr, "malloc error,errno:%d,%s", errno, strerror(errno));
exit(-1);
}
bzero(cli_inf, sizeof(client_inf));
Client_Link(cli_inf);
Get_Weather(cli_inf);
Parse_cJSON(cli_inf);
return 0;
}
//客户端连接服务器函数
int Client_Link(client_inf_p cli_inf)
{
//socket获取套接字
if ((cli_inf->sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "socket error, errno:%d,%s", errno, strerror(errno));
exit(-1);
}
struct sockaddr_in cliaddr;
bzero(&cliaddr, sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(CLI_PORT);
cliaddr.sin_addr.s_addr = inet_addr(CLI_IP);
//绑定套接字
if (bind(cli_inf->sock_fd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) == -1)
{
fprintf(stderr, "bind error, errno:%d,%s", errno, strerror(errno));
exit(-1);
}
struct sockaddr_in servaddr; //定义服务器IP信息结构体
struct sockaddr_in tmpaddr; //定义一个信息结构体接收域名IP
bzero(&servaddr, sizeof(servaddr));
struct hostent *host_inf = gethostbyname(DOMAIN_NAME); //定义并获取域名信息结构体
if (host_inf == NULL)
{
fprintf(stderr, "gethostbyname error,errno:%d,%s", errno, strerror(errno));
exit(-1);
}
memcpy(&tmpaddr.sin_addr, host_inf->h_addr, sizeof(struct in_addr)); //将网络字节序复制给sin_addr,方便后续inet_ntoa函数的字符串转换
strcpy(cli_inf->ip, inet_ntoa(tmpaddr.sin_addr)); //赋值常用结构体中IP
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = inet_addr(cli_inf->ip);
//开始连接服务器
if (connect(cli_inf->sock_fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
{
fprintf(stderr, "connect error,errno:%d,%s", errno, strerror(errno));
exit(-1);
}
printf("connect success!\n\n");
return 0;
}
//从服务器获取天气信息并转换成cJSON格式
void Get_Weather(client_inf_p cli_inf)
{
char buf[1024] = "\0";
//拼接http数据包
sprintf(buf, "GET https://%s/v3/weather/now.json?key=%s&location=%s&language=%s&unit=c HTTP/1.1\r\n"
"Host:api.seniverse.com\r\n"
"\r\n",
DOMAIN_NAME, KEY, LOCATION, LANGUAGE
);
//发送数据包
if (send(cli_inf->sock_fd, buf, strlen(buf), 0) == -1)
{
fprintf(stderr, "send error,errno:%d,%s", errno, strerror(errno));
exit(-1);
}
bzero(buf, sizeof(buf));
//接收服务器应答信息
if (recv(cli_inf->sock_fd, buf, sizeof(buf), 0) == -1)
{
fprintf(stderr, "recv error,errno:%d,%s", errno, strerror(errno));
exit(-1);
}
bzero(buf, sizeof(buf));
//接收服务器发送的数据
if (recv(cli_inf->sock_fd, buf, sizeof(buf), 0) == -1)
{
fprintf(stderr, "recv error,errno:%d,%s", errno, strerror(errno));
exit(-1);
}
//保存cJSON格式的根对象指针
cli_inf->root = cJSON_Parse(buf);
}
//解析cJSON格式信息
void Parse_cJSON(client_inf_p cli_inf)
{
char weather_msg[100] = "\0";
//第一层解析
cJSON * results = cJSON_GetObjectItem(cli_inf->root, "results");
//第二层解析
cJSON * obj = cJSON_GetArrayItem(results, 0);
//第三次解析
cJSON * location = cJSON_GetObjectItem(obj, "location");
cJSON * now = cJSON_GetObjectItem(obj, "now");
//第四层解析
cJSON * name = cJSON_GetObjectItem(location, "name");
//第四层解析
cJSON * text = cJSON_GetObjectItem(now, "text");
cJSON * temperature = cJSON_GetObjectItem(now, "temperature");
//获取并拼接所需数据
sprintf(weather_msg, "城市:%s\n天气:%s\n温度:%s\n", name->valuestring, text->valuestring, temperature->valuestring);
//输出信息
printf("%s\n", weather_msg);
}
标签:HTTP,cli,cJSON,errno,传输,client,inf,buf
From: https://www.cnblogs.com/colors-lg/p/18243375