文章目录
关于TCP/IP详细说明可参考《计算机网络(第7版)-谢希仁》
1、UDP通信:ESP8266作为客户端,手机作为服务器
代码
在工程中创建 user_udp.c、 user_udp.h文件
/*
* user_udp.c
*
* Created on: 2021年2月23日
* Author: Administrator
*/
#include "osapi.h"
#include "os_type.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"
#include "user_udp.h"
struct espconn user_udp_espconn;
os_timer_t checkTimer_wifistate;
void ICACHE_FLASH_ATTR
user_udp_sent_cb(void *arg) //发送
{
os_printf("\r\n ESP8266发送成功!\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; //本地端口,即ESP8266的端口
user_udp_espconn.proto.udp->remote_port = 10500; //目标端口,即测试手机中调试助手APP的端口
const char udp_remote_ip[4] = { 192, 168, 1, 107 }; //目标IP地址(广播),即测试手机中调试助手APP的IP地址
os_memcpy(user_udp_espconn.proto.udp->remote_ip, udp_remote_ip, 4);
espconn_send((struct espconn *) arg, "ESP8266已经收到数据!", strlen("ESP8266已经收到数据!"));
}
void ICACHE_FLASH_ATTR
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; //本地端口,即ESP8266的端口
user_udp_espconn.proto.udp->remote_port = 10500; //目标端口,即测试手机中调试助手APP的端口
const char udp_remote_ip[4] = { 192, 168, 1, 107 }; //目标IP地址(广播),即测试手机中调试助手APP的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_send(&user_udp_espconn, "ESP8266成功连接服务器", strlen("ESP8266成功连接服务器"));
}
}
void ICACHE_FLASH_ATTR
udp_client_init(void) // 在 user_init 函数中调用
{
wifi_set_opmode(0x01); //设置为STATION模式
struct station_config stationConf;
os_strcpy(stationConf.ssid, "TP-LINK_4607"); //测试手机连接的WIFI名
os_strcpy(stationConf.password, "weijing418"); //测试手机连接的wifi密码
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); //启动定时器,单位:毫秒
}
实验分析
ESP8266串口数据
手机端数据
注意:
1、手机端使用的测试软件是“网络助手”,在应用市场可以搜索到
2、注意程序中要改为自己测试中实际的IP地址和端口号;
3、ESP8266的IP地址是系统自动分配的;
2、UDP通信:ESP8266作为服务器,手机作为客户端
代码
#include "osapi.h"
#include "os_type.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"
#include "user_udp.h"
struct espconn user_udp_espconn;
static void ICACHE_FLASH_ATTR
user_udp_receive_cb(void *arg, char *pdata, unsigned short len)
{
os_printf("收到数据:%s\r\n", pdata); // %s,用来输出一个字符串
espconn_send((struct espconn *) arg, "已经收到", strlen("已经收到"));
}
static void ICACHE_FLASH_ATTR
user_udp_send_cb(void *arg)
{
os_printf("\r\n已发送\r\n");
}
void ICACHE_FLASH_ATTR
user_udp_config(void)
{
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 = 10500; //目标端口
espconn_regist_recvcb(&user_udp_espconn, user_udp_receive_cb); //注册接收回调函数
espconn_regist_sentcb(&user_udp_espconn, user_udp_send_cb); //注册发送回调函数
espconn_create(&user_udp_espconn); //建立UDP传输
}
void ICACHE_FLASH_ATTR
user_wifi_init(void) {
struct softap_config apConfig;
wifi_set_opmode(0x02); //设置为AP模式,并保存到 flash
apConfig.ssid_len = 10; //设置ssid长度
os_strcpy(apConfig.ssid, "HuaWei"); //设置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 ICACHE_FLASH_ATTR
udp_services_init(void) //在 user_init 函数中调用
{
os_printf("\r\n udp_services_init ... \r\n");
user_wifi_init();
user_udp_config();
}
测试步骤
手机连接ESP8266的WIFI
实验分析
ESP8266串口数据
手机端的网络助手数据
注意:
手机端没有收到ESP8266反馈的数据“已经收到”,原因?
3、TCP通信:ESP8266作为服务器,手机作为客户端
代码
/*
* user_tcp.c
*
* Created on: 2021年2月23日
* Author: Administrator
*/
#include "osapi.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"
#include "gpio.h"
/*-----------------------TCP test ESP8266 is server----------------------------------------------------------------------------------------*/
struct espconn user_tcp_espconn;
static void ICACHE_FLASH_ATTR
server_recv_cb(void *arg, char *pdata, unsigned short len) {
os_printf("收到手机发来的数据:%s \r\n", pdata);
espconn_send((struct espconn *) arg, "ESP8266已经收到数据", strlen("ESP8266已经收到数据"));
}
static void ICACHE_FLASH_ATTR
server_sent_cb(void *arg) {
os_printf("ESP8266数据发送成功!\r\n");
}
static void ICACHE_FLASH_ATTR
server_discon_cb(void *arg) {
os_printf("连接已经断开!\r\n");
}
static void ICACHE_FLASH_ATTR
server_listen_cb(void *arg) //注册 TCP 连接成功建立后的回调函数
{
struct espconn *pespconn = arg;
espconn_regist_recvcb(pespconn, server_recv_cb); //接收
espconn_regist_sentcb(pespconn, server_sent_cb); //发送
espconn_regist_disconcb(pespconn, server_discon_cb); //断开
}
static void ICACHE_FLASH_ATTR
server_recon_cb(void *arg, sint8 err) //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
{
os_printf("连接错误,错误代码为:%d \r\n", err); //%d,用来输出十进制整数
}
static void ICACHE_FLASH_ATTR
user_tcp_config(void)
{
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 = 2000; //本地端口,即ESP8266的端口
espconn_regist_connectcb(&user_tcp_espconn, server_listen_cb); //注册 TCP 连接成功建立后的回调函数
espconn_regist_reconcb(&user_tcp_espconn, server_recon_cb); //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
espconn_accept(&user_tcp_espconn); //创建 TCP server,建立侦听
espconn_regist_time(&user_tcp_espconn, 180, 0); //设置超时断开时间 单位:秒,最大值:7200 秒
}
static void ICACHE_FLASH_ATTR
tcp_wifi_init(void)
{
struct softap_config apConfig;
wifi_set_opmode(0x02); //设置为AP模式,并保存到 flash
apConfig.ssid_len = 10; //设置ssid长度
os_strcpy(apConfig.ssid, "mate40pro"); //设置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 ICACHE_FLASH_ATTR
tcp_service_init(void) //在 user_init 函数中调用
{
tcp_wifi_init();
user_tcp_config();
}
操作步骤
手机连接ESP8266的WIFI
实验分析
ESP8266串口数据
手机网络助手
4、TCP通信:ESP8266作为客户端,手机作为服务器
代码
/*
* user_tcp.c
*
* Created on: 2021年2月23日
* Author: Administrator
*/
#include "osapi.h"
#include "user_interface.h"
#include "espconn.h"
#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("ESP8266发送数据成功!\r\n");
}
void ICACHE_FLASH_ATTR
user_tcp_discon_cb(void *arg) //断开
{
os_printf("断开连接成功!\r\n");
}
void ICACHE_FLASH_ATTR
user_tcp_recv_cb(void *arg, //接收
char *pdata, unsigned short len) {
os_printf("ESP8266收到数据:%s\r\n", pdata);
espconn_send((struct espconn *) arg, "ESP8266已经收到数据", strlen("ESP8266已经收到数据"));
}
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, "ESP8266连接成功", strlen("ESP8266连接成功"));
}
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 ICACHE_FLASH_ATTR
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, 1, 107 };//目标IP地址,必须要先从手机获取,否则连接失败.
wifi_get_ip_info(STATION_IF, &info); //查询 WiFi模块的 IP 地址
my_station_init((struct ip_addr *) remote_ip, &info.ip, 10500);//连接到目标服务器的10500端口
}
}
void ICACHE_FLASH_ATTR
tcp_client_init(void) //在 user_init 函数中调用
{
wifi_set_opmode(0x01); //设置为STATION模式
struct station_config stationConf;
os_strcpy(stationConf.ssid, "TP-LINK_4607"); //改成你自己的 路由器的用户名
os_strcpy(stationConf.password, "weijing418"); //改成你自己的 路由器的密码
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); //启动定时器,单位:毫秒
}
操作步骤
ESP8266和手机连接在同一个WIFI下
实验分析
ESP8266串口数据
手机网络助手