ESP8266之TCP_Client

模块:esp-01s
SDK版本:ESP8266_RTOS_SDK-3.0
开发环境:wsl+vscode
功能模块:wifi,tcp_client
由于esp8266 sdk 2.0以后的版本似乎去掉了“espconn.h”头文件,网上的很多程序不能用了,官方文档也没跟得上sdk的更新速度,我们只能通过socket来实现tcp通信了。
关于socket基本知识,有一篇文章解释的比较清楚 Linux Socket编程(不限Linux)

本文代码tcp部分参考了 ESP8266_RTOS_SDK V3.0下TCP 通讯
本程序能够完成wifi重连,tcp断开重连,稳定可靠!

2018.9.30更新:解决了wifi断开后tcp不能重连的问题

编译基于ESP8266 RTOS SDK V3.0,由于sdk不断更新,不保证其他版本sdk能够使用
8266作为tcp client,连接到局域网的tcp server

#include<stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "rom/ets_sys.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>

#define STA_SSID "esp_test"
#define STA_PASS "12345678"
#define PORT_ADDR "192.168.1.243"

static EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;
static void http_get_task(void *pvParameters);
static const char *TAG = "example";

//wifi的回调事件注册
//static EventGroupHandle_t wifi_event_group;
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch(event->event_id) {
    //station模式下开始连接
    case SYSTEM_EVENT_STA_START:
        printf("开始连接wifi\n");
        esp_wifi_connect();
        break;
    //station模式下已完成连接并且获取到了IP
    case SYSTEM_EVENT_STA_GOT_IP: 
        //将其ip信息打印出来
        printf("获取到IP:%s\n",ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
        break;
    //station模式下 本设备从AP断开/AP踢了本设备
    case SYSTEM_EVENT_STA_DISCONNECTED:
        esp_wifi_connect();//重新连接之前的AP
        break;
    default:
        break;
    }
    return ESP_OK;
}  
void wifi_init_sta(void)
{
       //开始wifi 连接
    //wifi_event_group = xEventGroupCreate(); //创建一个事件组
    tcpip_adapter_init();           //初始化TCP/IP相关,这个函数只需要调用一次
    esp_event_loop_init(event_handler, NULL);   //注册事件
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg); //初始化wifi底层相关
    //构造需要连接的wifi信息
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = STA_SSID,  //填入wifi名称/ssid
            .password = STA_PASS //填入wifi密码
        },
    };
    esp_wifi_set_mode(WIFI_MODE_STA); //设置wifi模式,设置为station模式
    esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config); //将其wifi信息配置进去
    esp_wifi_start(); //开启wifi状态机 ()
}

static void http_get_task(void *pvParameters)
{
    char *servInetAddr = PORT_ADDR;
    struct sockaddr_in sockaddr;
    char recvline[64];
    char sendline[64]="hello world\n";
   while(1)
   {
    int s = socket(AF_INET, SOCK_STREAM, 0);//2,1,0
    if(s < 0) {
            printf("Socket  failed:%d\n",s);
            close(s);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        }
    memset(&sockaddr,0,sizeof(sockaddr));
    sockaddr.sin_family = AF_INET; //设定为ipv4
    sockaddr.sin_port = htons(60000); //设定端口号
    inet_pton(AF_INET,servInetAddr,&sockaddr.sin_addr);
        if((connect(s,(struct sockaddr*)&sockaddr,sizeof(sockaddr))) < 0 )
         {
            printf("Socket connect failed!\n");
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        }
        if (write(s, sendline, strlen(sendline)) < 0) {
            printf("Socket send failed\n");
            close(s);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        }
            while(1)
            {
               // memset(&recvline,0,sizeof(recvline));
                int iDataNum= recv(s,recvline,64,0);
                if(iDataNum>0){
               // recvline[iDataNum]='\0';
                recvline[iDataNum]='\0'; 
                 printf("%s\n",recvline); //接收到的数据
                }else if(iDataNum==0||get_wifi_status()==false)
                {
                //服务端或本地段意外/手动断开
                close(s);
                break;
                //跳出接收循环这样完成自动重连
                }
            }
   }
}

void app_main(void)
{
    // uart_set_baudrate(0,115200);//将串口设置成115200
     esp_err_t ret = nvs_flash_init();
     if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    printf("SDK version:%s\n", esp_get_idf_version());
    printf("ESP_WIFI_MODE_STA");//  打印当前模式                                                                                     
    wifi_init_sta();//station模式初始化
     //vTaskDelay(10000 / portTICK_PERIOD_MS);
    xTaskCreate(&http_get_task, "http_get_task", 16384, NULL, 5, NULL);

}

本文链接:

https://www.veryxs.com/index.php/archives/6/
1 + 5 =
快来做第一个评论的人吧~