通过上次讲了ESP8266的SDK基础开发和之前的介绍,相信大家对这块芯片已经有了比较详细的了解了,这一周我们就来讲讲更深一层的问题——网络开发。
网络通讯协议
网络通信协议是一种网络通用语言,为连接不同操作系统和不同硬件体系结构的互联网络引提供通信支持,是一种网络通用语言。
在单片机开发的项目中,我们一般会用到的是下面几种通讯协议:
UDP协议
UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成,提供面向事务的简单不可靠信息传送服务。UDP协议适用端口分别运行在同一台设备上的多个应用程序。UDP协议适用端口分别运行在同一台设备上的多个应用程序。TCP协议
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。
TCP/IP 协议具有很强的灵活性,支持任意规模的网络,几乎可连接所有服务器和工作站。在使用TCP/IP协议时需要进行复杂的设置,每个结点至少需要一个“IP地址”、一个“子网掩码”、一个“默认网关”、一个“主机名”,.
与UDP不同的是,TCP提供了一种面向连接的、可靠的字节流服务。面向连接比较好理解,就是连接双方在通信前需要预先建立一条连接,这犹如实际生活中的打电话。-
Http协议
超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。
当然,这里要说明的是Http并不是一种另外的独立的通讯协议。
HTTP是一个客户端和服务器端请求和应答的标准(TCP)。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求。
之所以把它单独开来说,是因为有一部分云平台提供的通讯只是Http而不是基层的TCP协议。了解了这一些之后,我们才能进行下一步。
TCP接口函数详解
由于TCP协议应用的广泛性和可靠性,所以我采用的是TCP通讯方式,因此这里我只讲TCP协议的开发。
ESP8266的SDK给我们提供的网络函数接口为 espconn 接口,以下所有接口函数都定义在(工程目录\include\espconn.h)
先介绍一个重要的结构体:
struct espconn {
/* espconn的类型 (TCP, UDP) */
enum espconn_type type;
/* espconn目前的模式 */
enum espconn_state state;
union {
esp_tcp *tcp;
esp_udp *udp;
} proto;
/* 与espconn 有关的回调函数 */
espconn_recv_callback recv_callback;
espconn_sent_callback sent_callback;
espconn_handle esp_pcb;
uint8 *ptrbuf;
uint16 cntr;
};
下面是我们一般会用到的接口函数:
- espconn_gethostbyname(struct espconn *pespconn, const char *hostname,ip_addr_t *addr, dns_found_callback found)
功能:域名解析
输入参数:
struct espconn *espconn——相应连接的控制块结构
const char *hostname——域名 string 指针
ip_addr_t *addr——ip 地址
dns_found_callback found——回调函数(即完成dns地址解析后的处理函数) - espconn_regist_sentcb(struct espconn *espconn,
espconn_sent_callback sent_cb)
功能:注册数据发送完成的回调函数,数据发送成功后回调
输入参数:
struct espconn *espconn——相应连接的控制块结构
espconn_sent_callback sent_cb——注册的回调函数 - *espconn_regist_recvcb(struct espconn espconn,
espconn_recv_callback recv_cb)
功能:注册数据接收函数,收到数据时回调
输入参数:
struct espconn *espconn——相应连接的控制块结构
espconn_connect_callback connect_cb——注册的回调函数 - *espconn_sent_callback (void arg)
功能:数据发送结束回调 - espconn_recv_callback (void *arg, char *pdata, unsigned short len)
功能:接收数据回调函数
输入参数:
void *arg——回调函数参数
char *pdata——接收数据入口参数
unsigned short len——接收数据长度 - espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length)
功能:发送数据
输入参数:
struct espconn *espconn——相应连接的控制块结构
uint8 *psent——sent 数据指针
uint16 length——sent 数据长度 - espconn_connect(struct espconn *espconn)
功能:建立 TCP 连接
输入参数:
struct espconn *espconn——相应连接的控制块结构 - *espconn_connect_callback (void arg)
功能:TCP 侦听或连接成功回调 - espconn_disconnect(struct espconn *espconn)
功能:断开 TCP 连接
输入参数:
struct espconn *espconn——相应连接的控制块结构 - espconn_regist_connectcb(struct espconn *espconn,
espconn_connect_callback connect_cb)
功能:注册 TCP 连接函数,成功连接时回调
输入参数:
struct espconn *espconn——相应连接的控制块结构
espconn_connect_callback connect_cb——注册的回调函数 - espconn_regist_reconcb(struct espconn *espconn,
espconn_connect_callback recon_cb)
功能:注册 TCP 重连函数,出错重连时回调
输入参数:
struct espconn *espconn——相应连接的控制块结构
espconn_connect_callback connect_cb——注册的回调函数 - espconn_regist_disconcb(struct espconn *espconn,
espconn_connect_callback discon_cb)
功能:注册断开 TCP 连接函数,断开连接成功时回调
输入参数:
struct espconn *espconn——相应连接的控制块结构
espconn_connect_callback connect_cb——注册的回调函数
TCP连接
基本的接口函数讲完,就来看看实例吧。
有认真看过我上次教程的读者肯定会发现我在user_set_station_config函数中调用了user_check_ip函数,那么该函数是干什么的呢?下面我就放出源代码:
user_check_ip(void)
{
struct ip_info ipconfig;
//disarm timer first
os_timer_disarm(&client_timer);
//get ip info of ESP8266 station
wifi_get_ip_info(STATION_IF, &ipconfig);
if (wifi_station_get_connect_status() ==
STATION_GOT_IP &&
ipconfig.ip.addr != 0)
{
os_printf("got ip !!! \r\n");
os_timer_disarm(&test_timer1);
os_timer_setfn(&test_timer1, (os_timer_func_t *)dns_found, NULL);
os_timer_arm(&test_timer1, 1000, 0);
}
else
{
if ((wifi_station_get_connect_status() == STATION_WRONG_PASSWORD ||
wifi_station_get_connect_status() == STATION_NO_AP_FOUND ||
wifi_station_get_connect_status() == STATION_CONNECT_FAIL))
{
os_printf("connect fail !!! \r\n");
}
else
{
//re-arm timer to check ip
os_timer_setfn(&client_timer,
(os_timer_func_t *)user_check_ip, NULL);
os_timer_arm(&client_timer, 100, 0);
}
}
}
其中
dns_found(void)
{
// if use http,put the url into “URL” next line
espconn_gethostbyname(&socket, URL , &address, dns_found);
/* if use the basic tcp mode
(you can change the esp_server_ip and remote_port as your mind)*/
const char esp_server_ip[4] = {xxx, xxx, xxx, xxx};
os_memcpy(user_conn.proto.tcp->remote_ip, esp_server_ip, 4);
user_conn.proto.tcp->local_port = espconn_port();
user_conn.proto.tcp->remote_port = xxxx;
espconn_regist_connectcb(&user_conn, user_esp_platform_connect_cb);
espconn_regist_reconcb(&user_conn, user_esp_platform_recon_cb);
user_esp_platform_connect(&user_conn);
}
总结
通过今天的介绍,大家对网络通讯也有了比较基础的了解了,可以根据自己的需要修改远程服务器的ip地址和端口来建立自己的tcp连接了,下期将带给大家带来云平台的选择和服务器通讯讲解。