Esp8266学习之旅⑧ 你要找的8266作为UDP、TCP客户端或服务端的角色通讯,都在这了。(带Demo)

来源:互联网 发布:龙岗网络推广 编辑:程序博客网 时间:2024/05/22 17:40

  • 本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。

    • 1、 Esp8266之 搭建开发环境,开始一个“hellow world”串口打印。

    • 2、 Esp8266之 利用GPIO开始使用按钮点亮你的“第一盏灯”。

    • 3、 Esp8266之 利用 “软件定时器 ” 定时0.5秒闪烁点亮一盏LED。

    • 4 、Esp8266之 了解PWM,更为深入地用PWM控制一盏LED的亮度变化。

    • 5 、Esp8266之 原生乐鑫SDK高级使用之封装Post与Get请求云端,拿到“天气预报信息”。

    • 6 、Esp8266之 了解 SmartConfig与Airkiss一键配网,给8266配网上云端。无需把wifi名字密码写在固件里。

    • 7 、Esp8266之 了解 softAP热点配网模式原理,仿“机智云”定义自己的热点配网模式协议。

    • 8、 Esp8266之 你要找的8266作为UDP、TCP客户端或服务端的角色通讯,都在这了。

    • 9、 Esp8266进阶之路第一篇: [小实战上篇]Windows系统搭建8266的本地Mqtt服务器,局域网点亮一盏LED灯。

    • 10、 Esp8266进阶之路第二篇: [小实战下篇]Windows系统搭建8266的本地Mqtt服务器,局域网点亮一盏LED灯。

    • 11、 Esp8266进阶之路第三篇: 8266接入阿里智能,点亮一盏LED灯,期待天猫精灵语音控制的不约而至!

    • 12、 Esp8266进阶之路第三篇: 图文并茂学习阿里云主机搭建8266MQTT服务器,实现移动网络远程控制


一、前言。

关于网络通讯,Maybe搞硬件的小伙伴不是很懂!因为关于UDP和TCP的协议是啥协议?有何不同?那本文仅仅做一个粗略的介绍!参考诸多资料,但会把其中的精华与要义介绍给大家!

  • 在网络传输应用层中,通常使用TCP和UDP这三种协议实现数据的传输。在传输过程中,需要双向的通讯连接实现数据的交互。因此,在这双向链路的一端称之为socket,一个socket有一个IP地址和端口号。

  • 目前流程的网络编程模型是客户端/服务端(C/S)结构。

  • UDP 是 User Datagram Protocol 的简称,是一种无连接、不可靠的协议,每一个数据报都是一个独立的信息,它在网络上以任何可能的路径传到目的地,但不保证是否真的传到目的地、是否过程中真的保证了数据的完整性!

  • TCP是Transmission Control Protocol的简称,是一个可靠的面向链接的协议,一旦成功建立连接,保证了数据的完整性传到目的地!

问题①:二者有什么区别!?

  • UDP就好似发短信,只管发出去,至于对方是不是空号(网络不可到达)能不能收到(丢包)等并不关心。

  • TCP好像打电话,双方要通话,首先,要确定对方不是开机(网络可以到达),然后要确定是不是没有信号(),然后还需要对方接听(通信链接)。

问题①:出现以上区别的优缺点!?

  • UDP无需等待对面的确认了,再发送数据过去。这执行效率较高,适合要求发送迅速、数据小的连接!

  • TCP要等待对面的确认,方可建立连接。也就是人们所说的“三次握手”,但是执行效率较慢,但是安全可靠,毕竟人家是保证了数据的完整性!


二、UDP客户端与服务端。

2.1 UDP客户端角色。

效果图:8266为UDP客户端,手机为UDP服务端)。

  • 知识点①:必须要服务端先开启,也即是手机先开启服务,设置对应的端口!然后8266开启UDP客户端去连接手机,进行通讯。

  • 知识点②:如果没有设置对端口对应,也会提示手机发送成功,因为UDP协议就是发送出去,不管是否到达目的地。

这里写图片描述


struct espconn user_udp_espconn;os_timer_t checkTimer_wifistate;void ICACHE_FLASH_ATTR user_udp_sent_cb(void *arg)   //发送{    os_printf("\r\n发送成功!\r\n");}void ICACHE_FLASH_ATTR user_udp_recv_cb(void *arg,    //接收        char *pdata, unsigned short len) {    os_printf("接收数据:%s", pdata);    //每次发送数据确保端口参数不变    user_udp_espconn.proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp));    user_udp_espconn.type = ESPCONN_UDP;    user_udp_espconn.proto.udp->local_port = 2000;    user_udp_espconn.proto.udp->remote_port = 8686;    const char udp_remote_ip[4] = { 255, 255, 255, 255 };    os_memcpy(user_udp_espconn.proto.udp->remote_ip, udp_remote_ip, 4);    espconn_sent((struct espconn *) arg, "已经收到啦!", strlen("已经收到啦!"));}void Check_WifiState(void) {    uint8 getState = wifi_station_get_connect_status();    //如果状态正确,证明已经连接    if (getState == STATION_GOT_IP) {        os_printf("WIFI连接成功!");        os_timer_disarm(&checkTimer_wifistate);        wifi_set_broadcast_if(0x01);     //设置 ESP8266 发送 UDP广播包时,从 station 接口发送        user_udp_espconn.proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp));//分配空间        user_udp_espconn.type = ESPCONN_UDP;              //设置类型为UDP协议        user_udp_espconn.proto.udp->local_port = 2000;            //本地端口        user_udp_espconn.proto.udp->remote_port = 8686;           //目标端口        const char udp_remote_ip[4] = { 255, 255, 255, 255 };       //目标IP地址(广播)        os_memcpy(user_udp_espconn.proto.udp->remote_ip, udp_remote_ip, 4);        espconn_regist_recvcb(&user_udp_espconn, user_udp_recv_cb);         //接收        espconn_regist_sentcb(&user_udp_espconn, user_udp_sent_cb);         //发送        espconn_create(&user_udp_espconn);            //建立 UDP 传输        espconn_sent(&user_udp_espconn, "连接服务器", strlen("连接服务器"));    }}void udp_client_init() //初始化{    wifi_set_opmode(0x01); //设置为STATION模式    struct station_config stationConf;    os_strcpy(stationConf.ssid, "meizu");     //改成你要连接的 路由器的用户名    os_strcpy(stationConf.password, "12345678"); //改成你要连接的路由器的密码    wifi_station_set_config(&stationConf);    //设置WiFi station接口配置,并保存到 flash    wifi_station_connect();   //连接路由器    os_timer_disarm(&checkTimer_wifistate);   //取消定时器定时    os_timer_setfn(&checkTimer_wifistate, (os_timer_func_t *) Check_WifiState,    NULL);    //设置定时器回调函数    os_timer_arm(&checkTimer_wifistate, 500, 1);      //启动定时器,单位:毫秒}

2.2 UDP服务端角色。

效果图:手机为UDP客户端,8266为UDP服务端)。

充当UDP服务端时候,要自身开启WIFI热点,等待设备接入,好比一个网关。手机接入8266热点WiFi时候,注意串口发出来的IP地址,此地址是手机要连接的UDP服务器的地址。

这里写图片描述

struct espconn user_udp_espconn;static void Inter213_Receive(void *arg, char *pdata, unsigned short len) {  //接收    os_printf("收到数据:%s\r\n", pdata); // %s,用来输出一个字符串    espconn_sent((struct espconn *) arg, "已经收到", strlen("已经收到"));}static void Inter213_Send_Cb(void *arg) {  //发送    os_printf("\r\n已发送\r\n");}void Inter213_InitUDP(int32_t Remote_port, uint32_t Local_port) {    user_udp_espconn.proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp));  //分配空间    user_udp_espconn.type = ESPCONN_UDP;  //设置类型为UDP协议    user_udp_espconn.proto.udp->local_port = Local_port;  //本地端口    user_udp_espconn.proto.udp->remote_port = Remote_port;  //目标端口    espconn_regist_recvcb(&user_udp_espconn, Inter213_Receive);  //接收    espconn_regist_sentcb(&user_udp_espconn, Inter213_Send_Cb);  //发送    espconn_create(&user_udp_espconn);  //建立UDP传输}void WIFI_Init() {    struct softap_config apConfig;    wifi_set_opmode(0x02);  //设置为AP模式,并保存到 flash    apConfig.ssid_len = 10;                     //设置ssid长度    os_strcpy(apConfig.ssid, "meizu");  //设置ssid名字,此名字是8266发射出来的WIfi    os_strcpy(apConfig.password, "12345678");   //设置密码    apConfig.authmode = 3;                      //设置加密模式    apConfig.beacon_interval = 100;            //信标间隔时槽100 ~ 60000 ms    apConfig.channel = 1;                      //通道号1 ~ 13    apConfig.max_connection = 4;               //最大连接数    apConfig.ssid_hidden = 0;                  //隐藏SSID    wifi_softap_set_config(&apConfig);      //设置 WiFi soft-AP 接口配置,并保存到 flash}void udp_services_init()        //初始化{    os_printf("\r\n udp_services_init ... \r\n");    WIFI_Init();    Inter213_InitUDP(8266, 8266);       //目标端口,本地端口}

三、TCP客户端与服务端。

2.1 TCP服务端角色。

效果图:手机为TCP客户端,8266为TCP服务端)。

充当服务端服务端时候,要自身开启WIFI热点,等待设备接入,好比一个网关。手机接入8266热点WiFi时候,注意串口发出来的IP地址,此地址是手机要连接的服务端的地址。注意好串口号即可通讯,此通讯100%保证到达目的地。

这里写图片描述


  • 代码:
#include "driver/uart.h"  #include "osapi.h"  #include "user_interface.h" #include "espconn.h"#include "mem.h" #include "gpio.h"struct espconn user_tcp_espconn;void ICACHE_FLASH_ATTR server_recv(void *arg, char *pdata, unsigned short len) {    os_printf("收到PC发来的数据:%s", pdata);    espconn_sent((struct espconn *) arg, "已经收到啦!", strlen("已经收到啦!"));}void ICACHE_FLASH_ATTR server_sent(void *arg) {    os_printf("发送成功!");}void ICACHE_FLASH_ATTR server_discon(void *arg) {    os_printf("连接已经断开!");}void ICACHE_FLASH_ATTR server_listen(void *arg)  //注册 TCP 连接成功建立后的回调函数{    struct espconn *pespconn = arg;    espconn_regist_recvcb(pespconn, server_recv);  //接收    espconn_regist_sentcb(pespconn, server_sent);  //发送    espconn_regist_disconcb(pespconn, server_discon);  //断开}void ICACHE_FLASH_ATTR server_recon(void *arg, sint8 err) //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连{    os_printf("连接错误,错误代码为:%d\r\n", err); //%d,用来输出十进制整数}void Inter213_InitTCP(uint32_t Local_port) {    user_tcp_espconn.proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp)); //分配空间    user_tcp_espconn.type = ESPCONN_TCP; //设置类型为TCP协议    user_tcp_espconn.proto.tcp->local_port = Local_port; //本地端口    espconn_regist_connectcb(&user_tcp_espconn, server_listen); //注册 TCP 连接成功建立后的回调函数    espconn_regist_reconcb(&user_tcp_espconn, server_recon); //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连    espconn_accept(&user_tcp_espconn); //创建 TCP server,建立侦听    espconn_regist_time(&user_tcp_espconn, 180, 0); //设置超时断开时间 单位:秒,最大值:7200 秒}void WIFI_Init() {    struct softap_config apConfig;    wifi_set_opmode(0x02);    //设置为AP模式,并保存到 flash    apConfig.ssid_len = 10;                     //设置ssid长度    os_strcpy(apConfig.ssid, "xuhongLove");     //设置wifi名字,注意这个是8266发出来的热点    os_strcpy(apConfig.password, "12345678");   //设置密码    apConfig.authmode = 3;                      //设置加密模式    apConfig.beacon_interval = 100;            //信标间隔时槽100 ~ 60000 ms    apConfig.channel = 1;                      //通道号1 ~ 13    apConfig.max_connection = 4;               //最大连接数    apConfig.ssid_hidden = 0;                  //隐藏SSID    wifi_softap_set_config(&apConfig);      //设置 WiFi soft-AP 接口配置,并保存到 flash}void tcp_service_init()     //初始化{    WIFI_Init();    Inter213_InitTCP(8266);     //本地端口}

2.1 TCP客户端角色。

效果图:8266为TCP客户端,手机为TCP服务端)。

充当TCP客户端,必须要知道服务端的IP地址。所以我先在手机开启TCP服务端的时候,拿到手机的IP地址,见下面的最左图!之后把IP地址拷贝到代码里,写成死的!这时候才通讯。

这里写图片描述


  • 代码:

  • 代码的实现过程,定时器开启先连接至路由器,待成功连接路由器,则关闭定时器,开启TCP客户端连接。


#include "driver/uart.h"  //串口0需要的头文件#include "osapi.h"  //串口1需要的头文件#include "user_interface.h" //WIFI连接需要的头文件#include "espconn.h"//TCP连接需要的头文件#include "mem.h" //系统操作需要的头文件#include "gpio.h"os_timer_t checkTimer_wifistate;struct espconn user_tcp_conn;void ICACHE_FLASH_ATTR user_tcp_sent_cb(void *arg)  //发送{    os_printf("发送数据成功!");}void ICACHE_FLASH_ATTR user_tcp_discon_cb(void *arg)  //断开{    os_printf("断开连接成功!");}void ICACHE_FLASH_ATTR user_tcp_recv_cb(void *arg,  //接收        char *pdata, unsigned short len) {    os_printf("收到数据:%s\r\n", pdata);    espconn_sent((struct espconn *) arg, "0", strlen("0"));}void ICACHE_FLASH_ATTR user_tcp_recon_cb(void *arg, sint8 err) //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连{    os_printf("连接错误,错误代码为%d\r\n", err);    espconn_connect((struct espconn *) arg);}void ICACHE_FLASH_ATTR user_tcp_connect_cb(void *arg)  //注册 TCP 连接成功建立后的回调函数{    struct espconn *pespconn = arg;    espconn_regist_recvcb(pespconn, user_tcp_recv_cb);  //接收    espconn_regist_sentcb(pespconn, user_tcp_sent_cb);  //发送    espconn_regist_disconcb(pespconn, user_tcp_discon_cb);  //断开    espconn_sent(pespconn, "8226", strlen("8226"));}void ICACHE_FLASH_ATTR my_station_init(struct ip_addr *remote_ip,        struct ip_addr *local_ip, int remote_port) {    user_tcp_conn.proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp));  //分配空间    user_tcp_conn.type = ESPCONN_TCP;  //设置类型为TCP协议    os_memcpy(user_tcp_conn.proto.tcp->local_ip, local_ip, 4);    os_memcpy(user_tcp_conn.proto.tcp->remote_ip, remote_ip, 4);    user_tcp_conn.proto.tcp->local_port = espconn_port();  //本地端口    user_tcp_conn.proto.tcp->remote_port = remote_port;  //目标端口    //注册连接成功回调函数和重新连接回调函数    espconn_regist_connectcb(&user_tcp_conn, user_tcp_connect_cb);//注册 TCP 连接成功建立后的回调函数    espconn_regist_reconcb(&user_tcp_conn, user_tcp_recon_cb);//注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连    //启用连接    espconn_connect(&user_tcp_conn);}void Check_WifiState(void) {    uint8 getState;    getState = wifi_station_get_connect_status();    //查询 ESP8266 WiFi station 接口连接 AP 的状态    if (getState == STATION_GOT_IP) {        os_printf("WIFI连接成功!\r\n");        os_timer_disarm(&checkTimer_wifistate);        struct ip_info info;        const char remote_ip[4] = { 192, 168, 43, 1 };//目标IP地址,必须要先从手机获取,否则连接失败.        wifi_get_ip_info(STATION_IF, &info);    //查询 WiFi模块的 IP 地址        my_station_init((struct ip_addr *) remote_ip, &info.ip, 6000);//连接到目标服务器的6000端口 }}void tcp_client_init()  //初始化{    wifi_set_opmode(0x01);  //设置为STATION模式    struct station_config stationConf;    os_strcpy(stationConf.ssid, "meizu");     //改成你自己的   路由器的用户名    os_strcpy(stationConf.password, "12345678"); //改成你自己的   路由器的密码    wifi_station_set_config(&stationConf);  //设置WiFi station接口配置,并保存到 flash    wifi_station_connect(); //连接路由器    os_timer_disarm(&checkTimer_wifistate); //取消定时器定时    os_timer_setfn(&checkTimer_wifistate, (os_timer_func_t *) Check_WifiState,    NULL);  //设置定时器回调函数    os_timer_arm(&checkTimer_wifistate, 500, 1);    //启动定时器,单位:毫秒}

四、备注。

由于比较本博文特殊,所以上个烧录图:

这里写图片描述

本8266的Demo下载地址:http://download.csdn.net/download/xh870189248/10149793

安卓APK下载,最好在安卓6.0系统以下版本运行,因为APK来源网络,没有源码不能修复适配,后期我也会出网络调试助手,敬请期待:http://download.csdn.net/download/xh870189248/10148287

8266代码工程教程汇总:https://github.com/xuhongv/StudyInEsp8266

阅读全文
0 0