ESP8266_AP模式、UDP的服务器or客户端
1、介绍
ESP8266工作在AP模式,创建一个WiFi局域网,笔记本连接此WiFi;
ESP8266,IP:192.168.4.1,端口:8266;
网络调试助手,IP:192.168.4.2,端口:6666;
使用UDP连接,有数据直接发,不需要建立连接;
客户端/服务器模式,服务器先运行,客户端要知道服务器的IP和端口,然后就可以发送UDP数据报,服务器接收UDP数据报,这时服务器也知道客户端的IP和端口了,可以响应客户端,即发送UDP数据报;
下面介绍ESP8266做为UDP连接的服务器,服务器和客户端其实并没多大区别,只不过作为服务器一开始你只要把自己端口设置好,等着就行了;作为客户端不仅要设置自己的端口,也要知道对方的IP和端口,仅此而已,文末有对比;
2、ESP8266作为UDP连接的服务器
2.1、设置ESP8266为AP模式,两步
- 设置ESP8266工作模式为AP;
- 配置AP参数:SSID、password、加密方式、是否隐藏WiFi名...
#define ESP8266_AP_SSID "LOVEYOU"
#define ESP8266_AP_PASS "Be Happy"//初始化AP模式,设置WiFi名和密码
void ICACHE_FLASH_ATTR AP_mode_init()
{struct softap_config ap_config;wifi_set_opmode(0x02); // 设置为AP模式,并保存到Flashos_memset(&ap_config, 0, sizeof(struct softap_config)); // AP参数结构体 = 0os_strcpy(ap_config.ssid,ESP8266_AP_SSID); // 设置SSID(将字符串复制到ssid数组)os_strcpy(ap_config.password,ESP8266_AP_PASS); // 设置密码(将字符串复制到password数组)ap_config.ssid_len=os_strlen(ESP8266_AP_SSID); // 设置ssid长度(和SSID的长度一致)ap_config.channel=1; // 通道号1~13ap_config.authmode=AUTH_WPA2_PSK; // 设置加密模式ap_config.ssid_hidden=0; // 不隐藏SSIDap_config.max_connection=4; // 最大连接数ap_config.beacon_interval=100; // 信标间隔时槽100~60000 mswifi_softap_set_config(&ap_config); // 设置soft-AP,并保存到Flash}
2.2、初始化UDP通信_espconn_create()
所谓初始化UDP通信,就是初始化一个全局的struct espconn变量,里面的信息有:
- 选择TCP或UDP通信;
- 连接状态;
- TCP/UDP协议下,本机和远端的IP及port;
- 发送、接收数据报的回调函数;
- 连接数;
struct espconn {/** type of the espconn (TCP, UDP) */enum espconn_type type;/** current state of the espconn */enum espconn_state state;union {esp_tcp *tcp;esp_udp *udp;} proto;/** A callback function that is informed about events for this espconn */espconn_recv_callback recv_callback;espconn_sent_callback sent_callback;uint8 link_cnt;void *reverse;
};
//此结构体,选择TCP/UDP,端口等信息;
struct espconn ST_NetCon; //必须定义为全局变量,内核将会使用此变量(内存)void UDP_send_callback();
void UDP_recv_callback(void * arg, char * pdata, unsigned short len);//初始化UDP通信,端口8266;
void ICACHE_FLASH_ATTR UDP_port8266_init()
{ST_NetCon.type = ESPCONN_UDP; //通信协议:UDPST_NetCon.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); // 申请内存//ST_NetCon.proto.udp->local_port = espconn_port(); //获取8266可用端口,这是动态的端口ST_NetCon.proto.udp->local_port = 8266 ; // 设置本地端口espconn_regist_sentcb(&ST_NetCon,UDP_send_callback); // 注册网络数据发送成功的回调函数espconn_regist_recvcb(&ST_NetCon,UDP_recv_callback); // 注册网络数据接收成功的回调函数espconn_create(&ST_NetCon); //初始化UDP通信
}void UDP_send_callback()
{os_printf("UDP seriver send over\n");
}//作为服务器收到客户端UDP报文的回调函数(参数列表必须是这些)
//arg:网络传输结构体espconn指针,保存客户端的IP和端口
//pdata:报文的数据指针
//len:报文的长度
void UDP_recv_callback(void * arg, char * pdata, unsigned short len)
{struct espconn * T_arg = arg; // 缓存网络连接结构体指针remot_info * P_port_info = NULL; // 远端连接信息结构体指针u8 buffer[20];os_printf("\nESP8266_Receive_Data = %s\n",pdata); // 串口打印接收到的数据// 获取远端信息【UDP通信是无连接的,向远端主机回应时需获取对方的IP/端口信息】if(espconn_get_connection_info(T_arg, &P_port_info, 0)==ESPCONN_OK) // 获取远端信息{T_arg->proto.udp->remote_port = P_port_info->remote_port; // 获取对方端口号T_arg->proto.udp->remote_ip[0] = P_port_info->remote_ip[0]; // 获取对方IP地址T_arg->proto.udp->remote_ip[1] = P_port_info->remote_ip[1];T_arg->proto.udp->remote_ip[2] = P_port_info->remote_ip[2];T_arg->proto.udp->remote_ip[3] = P_port_info->remote_ip[3];//os_memcpy(T_arg->proto.udp->remote_ip,P_port_info->remote_ip,4); // 内存拷贝}//显示远端主机IP地址os_sprintf(buffer,"IP:%d.%d.%d.%d",T_arg->proto.udp->remote_ip[0],T_arg->proto.udp->remote_ip[1],T_arg->proto.udp->remote_ip[2],T_arg->proto.udp->remote_ip[3]);oled_show_string(0,2,buffer,FONT_8x16);// 向对方发送应答espconn_send(T_arg,"ESP8266_WIFI_Recv_OK",os_strlen("ESP8266_WIFI_Recv_OK"));}
2.3、辅助代码、以及user_init
os_timer_t timer_ap_check; //检测AP模式设置完成,已能获取本机IP定时器//检测AP模式设置完成,已能获取本机IP定时器
void timer_ap_check_callback()
{struct ip_info IP_info;u8 ip_dec[4];u8 buffer[20];// 查询并打印ESP8266的工作模式switch(wifi_get_opmode()) // 输出工作模式{case 0x01: os_printf("\nESP8266_Mode = Station\n"); break;case 0x02: os_printf("\nESP8266_Mode = SoftAP\n"); break;case 0x03: os_printf("\nESP8266_Mode = Station+SoftAP\n"); break;}//AP模式下,默认开启DHCP,默认IP:192.168.4.1//-----------------------------------------------------------------------------------wifi_get_ip_info(SOFTAP_IF,&IP_info); // 参数2:IP信息结构体指针if(IP_info.ip.addr != 0){ //已获取到本机IP地址,初始化UDP//32位二进制IP地址,将它转换为点分十进制的形式ip_dec[0] = IP_info.ip.addr;ip_dec[1] = IP_info.ip.addr>>8;ip_dec[2] = IP_info.ip.addr>>16;ip_dec[3] = IP_info.ip.addr>>24;// 打印ESP8266的IP地址os_printf("ESP8266_IP = %d.%d.%d.%d\n",ip_dec[0],ip_dec[1],ip_dec[2],ip_dec[3]);os_sprintf(buffer,"IP:%d.%d.%d.%d",ip_dec[0],ip_dec[1],ip_dec[2],ip_dec[3]);oled_show_string(0,0,buffer,FONT_8x16);//初始化UDPUDP_port8266_init();//关闭定时器os_timer_disarm(&timer_ap_check);}else{os_printf("waiting a minute...\n");}// 查询并打印接入此WIFI的设备数量//os_printf("Number of devices connected to this WIFI = %d\n",wifi_softap_get_station_num());}void ICACHE_FLASH_ATTR timer_init()
{os_timer_disarm(&timer_ap_check);os_timer_setfn(&timer_ap_check,timer_ap_check_callback,NULL);os_timer_arm(&timer_ap_check,1000,1);}//*******************用户初始化函数**********************
void ICACHE_FLASH_ATTR user_init(void)
{u8 i;uart_init(115200,115200);my_delay_ms(1000); //等待串口稳定,避免起始数据错误system_soft_wdt_feed(); //喂狗,防止复位AP_mode_init(); //设置AP模式oled_init();timer_init();}
关于AP的头文件别忘了...
#include "ip_addr.h" // 被"espconn.h"使用,在"espconn.h"开头#include"ip_addr.h"或#include"ip_addr.h"放在"espconn.h"之前
#include "espconn.h" // TCP/UDP接口
3、下载、验证
当笔记本接入此WiFi时,提示station:f4:96:34:f5:bd:47加入此AP,这一串是笔记本的MAC地址;
ESP8266与笔记本之间的链路层传输,就要用到MAC地址;


4、作为服务器、客户端的不同
作为服务器:
- proto.udp 只提供本地端口local port;
- 等待接收UDP数据报,进入接收回调函数;
//初始化UDP通信,端口8266;
void ICACHE_FLASH_ATTR UDP_port8266_init()
{ST_NetCon.type = ESPCONN_UDP; //通信协议:UDPST_NetCon.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); // 申请内存//ST_NetCon.proto.udp->local_port = espconn_port(); //获取8266可用端口,这是动态的端口ST_NetCon.proto.udp->local_port = 8266 ; // 设置本地端口espconn_regist_sentcb(&ST_NetCon,UDP_send_callback); // 注册网络数据发送成功的回调函数espconn_regist_recvcb(&ST_NetCon,UDP_recv_callback); // 注册网络数据接收成功的回调函数espconn_create(&ST_NetCon); //初始化UDP通信
}
作为客户端:
- proto.udp 提供本地端口local port,远端IP和port;
- 就可以espconn_send,主动发送UDP数据报;
//初始化UDP通信,端口8266;
void ICACHE_FLASH_ATTR UDP_port8266_init()
{ST_NetCon.type = ESPCONN_UDP; //通信协议:UDPST_NetCon.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); // 申请内存//ST_NetCon.proto.udp->local_port = espconn_port(); //获取8266可用端口,这是动态的端口ST_NetCon.proto.udp->local_port = 8266 ; // 设置本地端口ST_NetCon.proto.udp->remote_ip[0] = 192;ST_NetCon.proto.udp->remote_ip[1] = 168;ST_NetCon.proto.udp->remote_ip[2] = 4;ST_NetCon.proto.udp->remote_ip[3] = 2;ST_NetCon.proto.udp->remote_port = 6666;espconn_regist_sentcb(&ST_NetCon,UDP_send_callback); // 注册网络数据发送成功的回调函数espconn_regist_recvcb(&ST_NetCon,UDP_recv_callback); // 注册网络数据接收成功的回调函数espconn_create(&ST_NetCon); //初始化UDP通信espconn_send(&ST_NetCon,"I am ESP8266.",strlen("I am ESP8266."));
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
