前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ESP8266_15天气预报之TCP的GET操作

ESP8266_15天气预报之TCP的GET操作

作者头像
MCU起航
发布2020-06-29 11:53:09
6180
发布2020-06-29 11:53:09
举报
文章被收录于专栏:单片机爱好者单片机爱好者

前面几节,TCP的基本操作聊了一些。接下来这几节,聊一聊HTTP协议下的GET操作。首先明确几个基本概念:

HTTP(HyperText Transfer Protocol,超文本传输协议)是一套计算机通过网络进行通信的规则,使HTTP客户端能够从HTTP服务器端请求到信息和服务,目前的版本号是1.1。

HTTP通讯机制是在一次完整的HTTP通讯过程中,客户端和服务器之间建立连接分为以下几个步骤。

1、建立连接:其中包括:域名解析,TCP三次握手。

2、发送数据

3、返回数据

4、关闭连接

咱们这一节主要研究的是其中的前二个步骤:建立连接和发送数据。即域名如何解析,数据该以什么样的格式发送。

如何演示?天气预报?

是的,天气预报。这个东西虽然有点俗,但用来讲解,效果还是挺好的。

首先,去心知天气(自行百度,非广告)注册一个账户,然后购买一个免费版的产品。这时,你就能通过API查看全国任意城市的天气了。

使用方式,将 API 密钥中的“私钥”作为 API 请求中的 key 参数值:

https://api.seniverse.com/v3/weather/now.json?key=your_private_key&location=beijing&language=zh-Hans&unit=c

把连接中的加黑字体换成你的私钥,然后粘贴到浏览器,效果如下:

看不清图片的,看下面文字:

{"results":[{"location":{"id":"WX4FBXXFKE4F","name":"北京","country":"CN","path":"北京,北京,中国","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"now":{"text":"多云","code":"4","temperature":"27"},"last_update":"2019-09-17T14:25:00+08:00"}]}

想看其它城市的天气,更换连接中的文字:beijing为你想要的城市即可。

先说域名解析,为什么要解析?

研究这个之前,先思考一个问题,我们上网的时候,究竟是怎么上的。以百度为例,我们输入的网址是:www.baidu.com或者http://www.baidu.com,再或者https://www.baidu.com。

严格来说,URL应该符合以下形式:

<协议>://<主机>:<端口>/<路径>?<参数>&<参数>

协议常用的有http、https或者ftp;“://”不能省略;主机就是“www”开头的网址,端口没有写的话,默认80;斜杠后面跟的是路径等等。对照这个格式,百度的网址可以写成这样:

http://www.baidu.com:80/index.html

所以,做域名解析的时候,要考虑这几方面的因素:协议、主机、端口、路径,也就是说你要把这几样因素都找到。域名解析的函数网上有很多公开的代码,我这里贴一个,仅供参考:

代码语言:javascript
复制
void ICACHE_FLASH_ATTR http_parse_request_url(char *URL,char *host,char *filename,unsigned short *port)
{
   char *PA;
   char *PB;
   memset(host,0,sizeof(host));
   memset(filename,0,sizeof(filename));
   port=0;    if(!(URL)) return;
   PA=URL;
   if(!strncmp(PA,"http://",strlen("http://")))
       PA=URL+strlen("http://");
   if(!strncmp(PA,"https://",strlen("https://")))
       PA=URL+strlen("https://");
   PB=strchr(PA,'/');
   if(PB){
       memcpy(host,PA,strlen(PA)-strlen(PB));
       if(PB+1){
           memcpy(filename,PB+1,strlen(PB-1));
           filename[strlen(PB)-1]=0;
       }
       host[strlen(PA)-strlen(PB)]=0;
   }else{
       memcpy(host,PA,strlen(PA));
       host[strlen(PA)]=0;
   }
   PA=strchr(host,':');
   if(PA)
       *port=atoi(PA+1);
   else
       *port=80;
}

所以,解析完成之后,得到主机和路径,按照相应格式,组成数据包,发送给服务器,服务器就能返回相应的数据。

那么,ESP8266怎么发送?直接通过espconn_sent函数把数据发出去?那是肯定不行滴。需要一个特定的格式。HTTP请求数据格式如下:

当浏览器发送请求时,它要向服务器发送一个数据块,也就是请求信息,其中信息由三部分组成。

1. 请求方法 URI协议/版本

2. 请求头(Request Header)

3. 请求正文

示范代码如下:

代码语言:javascript
复制
GET/sample.jspHTTP/1.1

Accept:image/gif.image/jpeg,*/*

Accept-Language:zh-cn

Connection:Keep-Alive

Host:localhost

User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)

Accept-Encoding:gzip,deflate

再比如,当我使用浏览器访问网址的时候,通过抓包工具,可以看到如下信息:

这些内容,有些是可以不要的。所以最终整理一下,以访问心知天气的API为例,实际的内容格式如下:

代码语言:javascript
复制
GET v3/weather/now.json?key=your_private_key&location=beijing&language=zh-Hans&unit=c HTTP/1.1

Accept: */*

Host: api.seniverse.com

Connection: Keep-Alive

GET后面跟的是前面那个API网址中,api.seniverse.com后面的那一串字符,然后是“HTTP/1.1”。

实际应用中,每次输入不同的API链接,我们不可能手动把前面的host和后面的字符串拆分开,所以需要上面的解析函数,用来判断哪部分是host,哪部分是字符串。

程序修改完成,保存、清理、编译、下载一条龙,然后重新上电。这里借助串口助手来查看效果。效果如下所示:

从receive data开始,都是收到的信息。我这里查看了廊坊的天气,显示晴天,28度,还可以~

但是目前这个数据只能通过串口打印出来,而且还有一定的格式,需要对格式进行解析,这部分下一节再说。

链接:

https://pan.baidu.com/s/1SkngvsrzbOJ2R-YWwbZrFQ

提取码:rco4

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 单片机爱好者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档