ESP32C3实现TCP客户端和本地服务器

ESP32C3实现TCP客户端和本地服务器

/*本地TCP服务器端和客户端*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "nvs_flash.h"
#include "wifi_provisioning/manager.h"
#include "wifi_provisioning/scheme_softap.h"
#include "socket.h"
/*宏定义*/
#define ERASE_NVS 0
// 清除储存的wifi密码->0: 沿用上次的WIFI信息进行连接; 1: 清除WIFI信息,使用SOFTAP一键配网进行新链接
#define TCP_SERRVER_OR_CLIENT 1
// 0: 服务器; 1: 客户端
/*函数声明*/
void WIFI_CALLBACK_FUN(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data); // 事件队列回调函数
void wifi_connect(void);                                                                                          // WIFI连接处理函数
/*全局变量*/

/***************************************************************************************************************/
/*MAIN函数*/
void app_main(void)
{
    wifi_connect(); // 连接wifi

#if TCP_SERRVER_OR_CLIENT != 0 // TCP客户端
    /*1. 创建套接字*/
    int sock_fd = socket(AF_INET, SOCK_STREAM, 0); // 创建套接字
    if (sock_fd < 0)
        goto error;
    /*2. 连接服务器*/
    struct sockaddr_in srvr_info =
        {
            .sin_family = AF_INET,
            .sin_addr.s_addr = inet_addr("192.168.137.156"),
            .sin_port = htons(65530)};
    int ret = connect(sock_fd, (struct sockaddr *)&srvr_info, sizeof(srvr_info));
    if (ret != 0)
    {
        printf("ERRORNO: %d\n", errno);
        for (int i = 0; i < 10; i++)
        {
            printf("正在尝试第%d次连接服务器...\n", i);
            if (0 == connect(sock_fd, (struct sockaddr *)&srvr_info, sizeof(srvr_info)))
                break;
            vTaskDelay(100);
            if (i == 9)
            {
                printf("connect函数出错,服务器无法连接!\n");
                goto error;
            }
        }
    }
    /*3. 发送数据给服务器*/
    int snd_cnt = 0;
    char *snd_dt = "Hello Server.";
    while (1)
    {
        snd_cnt++;
        send(sock_fd, snd_dt, strlen(snd_dt), 0);
        vTaskDelay(200);
        printf("第%d次发送数据到服务器!\n", snd_cnt);
    }
    shutdown(sock_fd, 0);
    close(sock_fd);
#else // TCP服务器
    /* 1. 创建套接字 */
    int fd = socket(AF_INET, SOCK_STREAM, 0); // IPV4, TCP
    if (fd < 0)
        goto error;
    /* 1.x 进行连接中断处理设置 */
    // int opt_val = 1;
    // setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(int));//服务器出现等待时间超时确保server能够重启成功

    /* 2. 绑定IP和端口号 */
    struct sockaddr_in bind_addr =
        {
            .sin_family = AF_INET,
            .sin_addr.s_addr = htonl(inet_addr("0.0.0.0")), // 0x00 00 00 00UL表示不对报文源地址进行验证
            .sin_port = htons(3333)};
    int ret = bind(fd, (struct sockaddr *)&bind_addr, sizeof(struct sockaddr)); // 绑定fd, IP和端口
    if (ret < 0)
        goto error;

    /* 3. 监听 */
    ret = listen(fd, 1); // 套接字fd,允许连接数量1
    if (ret < 0)
        goto error;

    /* 4. 等待客户端连接 */
    // u32_t ip_info = inet_addr("192.168.137.156");     //将点分IP转换为整型
    struct sockaddr_in client_addr = {0}; // 为accept连接的客户端保存IP
    u32_t client_addr_len = sizeof(client_addr);
    int clnt_fd = -1;
    for (;;)
    {
        clnt_fd = accept(fd, (struct sockaddr *)&client_addr, &client_addr_len); // 监听等待客户端连接
        if (clnt_fd >= 0)                                                        // 客户端连接成功
        {
            // printf("客户端连接成功, 客户端的IP地址为:%s\n",inet_ntoa(ip_info));
            printf("客户端连接成功,客户端的IP地址为:%s\n", inet_ntoa(client_addr.sin_addr.s_addr));
            break;
        }
    }

    /* 5. 连接成功,进行数据发送 */
    int len = 0;
    char rev_dat[1024] = {0};
    int rcv_cnt = 0;
    while (1)
    {
        rcv_cnt++;
        len = recv(clnt_fd, rev_dat, 1023, 0); // 阻塞接收数据,接收到数据后跳出recv函数
        if (len > 0)                           // 接收到数据
        {
            printf("第%d次接收到IP为%s的数据为: %s, 数据长度为:%d\n", rcv_cnt, inet_ntoa(client_addr.sin_addr.s_addr), rev_dat, len);
            strncpy(rev_dat + strlen(rev_dat), "\0", 1);    // 在字符末位增加换行符
            send(clnt_fd, rev_dat, strlen(rev_dat) + 1, 0); // 将接收到的数据发送回客户端
        }
        else if (len == 0) // 连接中断
        {
            printf("连接中断!正在等待新连接...\n");
            close(clnt_fd);
            rcv_cnt = 0;
            for (;;)
            {
                clnt_fd = accept(fd, (struct sockaddr *)&client_addr, &client_addr_len); // 监听等待新的客户端连接
                if (clnt_fd > 0)
                {
                    printf("新链接已经建立!\n");
                    break;
                }
            }
        }
        else
        {
            printf("退出!\n");
            break;
        }
        vTaskDelay(1); // 防止看门狗复位
        printf("标记\n");
    }
    shutdown(clnt_fd, 0); // 用于任何类型的 套接口禁止接收、禁止发送或禁止收发
    close(clnt_fd);
    close(fd);
#endif
error:
    while (1)
        ;
}
/**********************************************************************************************/
/*回调函数*/
void WIFI_CALLBACK_FUN(void *event_handler_arg, esp_event_base_t eb, int32_t ei, void *event_data)
{
    if (eb == WIFI_EVENT)
    {
        if (ei == WIFI_EVENT_STA_START)
        {
            esp_wifi_connect(); // 开始连接WIFI
            printf("正在连接WIFI!\n");
        }
        if (ei == WIFI_EVENT_STA_DISCONNECTED)
        {
            printf("自动连接失败,正在启动SOFTAP配网服务!\n");
            const char *pop = "abcd1234";
            const char *wifi_name = "SOFTAP_PROV_MGR_PROB";
            const char *wifi_key = "12345678";
            wifi_prov_mgr_start_provisioning(WIFI_PROV_SECURITY_1, pop, wifi_name, wifi_key);
            wifi_prov_mgr_wait();
            wifi_prov_mgr_deinit();
            printf("Provisioning服务结束,连接WIFI成功!\n");
        }
    }
    if (eb == IP_EVENT && ei == IP_EVENT_STA_GOT_IP)
    {
        printf("WIFI连接成功!\n");
        ip_event_got_ip_t *sta_ip = (ip_event_got_ip_t *)event_data;
        printf("本机IP地址为: " IPSTR "\n", IP2STR(&sta_ip->ip_info.ip));
    }
}
/*连接WIFI*/
void wifi_connect(void)
{
    nvs_flash_init();
#if ERASE_NVS != 0
    nvs_flash_erase();
    nvs_flash_init();
#endif
    esp_event_loop_create_default(); // 创建默认事件队列
    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, WIFI_CALLBACK_FUN, NULL, NULL);
    esp_netif_init();                    // 初始化网卡
    esp_netif_create_default_wifi_ap();  // 创建默认网卡ap
    esp_netif_create_default_wifi_sta(); // 创建默认网卡sta
    wifi_init_config_t esp_wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&esp_wifi_init_config); // 初始化WIFI功能
    /*softAP配网*/
    wifi_prov_mgr_config_t wifi_prov_mgr_config_t =
        {
            .scheme = wifi_prov_scheme_softap,
            .app_event_handler = WIFI_PROV_EVENT_HANDLER_NONE};
    wifi_prov_mgr_init(wifi_prov_mgr_config_t);
    bool wifi_prov_mgr_diag = false;
    wifi_prov_mgr_is_provisioned(&wifi_prov_mgr_diag);
    if (wifi_prov_mgr_diag == false)
    {
        const char *pop = "abcd1234";
        const char *wifi_name = "SOFTAP_PROV_MGR_PROB";
        const char *wifi_key = "12345678";
        wifi_prov_mgr_start_provisioning(WIFI_PROV_SECURITY_1, pop, wifi_name, wifi_key);
        wifi_prov_mgr_wait();
        wifi_prov_mgr_deinit();
        printf("Provisioning服务结束,连接WIFI成功!\n");
    }
    else
    {
        esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_START, WIFI_CALLBACK_FUN, NULL, NULL);        // 注册WIFI开启事件
        esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, WIFI_CALLBACK_FUN, NULL, NULL);    // 注册WIFI连接事件
        esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, WIFI_CALLBACK_FUN, NULL, NULL); // 注册WIFI连接失败事件
        esp_wifi_start();
    }
    esp_wifi_set_ps(WIFI_PS_NONE); // 关闭WIFI的省电模式
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值