乐鑫技术交流
直播中

俞舟群

7年用户 1058经验值
擅长:可编程逻辑 电源/新能源
私信 关注
[问答]

ESP8266当作TCP服务器,关于WIFI客户端连接数量问题求解

ESP8266当作TCP服务器,手机应用去连接,手机应用会重复连接,连接前会把之前的连接给断开,但是ESP8266的连接数一直在增加,当达到5个连接后,就再也不能连接通信了,现在的做法是,在ESP8266中把上一个连接断开,代码如下,但是不生效,帮忙看看哪有问题
static struct espconn led_wifi_conn;
static struct espconn *laster_wifi_conn;
static struct espconn *current_wifi_conn;
static esp_tcp led_wifi_tcp;
static uint8 led_tcp_dis;

// 此函数一直没有调用
static void led_wifi_disconnect_callback(void *arg)
{
        os_printf("led_wifi_disconnect_callbackn");
}

// 此函数一直没有调用
static void led_wifi_reconnect_callback(void *arg,sint8 err)
{
        os_printf("led_wifi_reconnect_callback err = %dn",err);
}

static void led_wifi_rev_callback(void *arg, char *pdata, unsigned short len)
{
        // os_printf("led_wifi_rev_callback led = %dn",len);
        UART1GetData(pdata,len);
}

static void led_wifi_send_callback(void *arg)
{
        // os_printf("led_wifi_send_callbackn");      
}

static void led_wifi_connect_callback(void *arg)
{
        struct espconn *conn;

        conn = (struct espconn *)arg;

        if ((unsigned int)arg == (unsigned int)&led_wifi_conn)
                os_printf("IS the samen");
        else
                os_printf("NOT the samen");
      
        os_printf("led_wifi_connect_callbackn");
        os_printf("conn->link_cnt = %dn",conn->link_cnt);
        os_printf("conn->state = %dn",conn->state);
        os_printf("current_wifi_conn = 0x%xn",(unsigned int)conn);
        current_wifi_conn = conn;
        led_tcp_dis       = 1;
        conn->proto.tcp = &led_wifi_tcp;
      
        espconn_regist_disconcb(conn,led_wifi_disconnect_callback);
        espconn_regist_reconcb(conn,led_wifi_reconnect_callback);
        espconn_regist_recvcb(conn, led_wifi_rev_callback);
        espconn_regist_sentcb(conn, led_wifi_send_callback);
}

static void led_wifi_build_tcp(void)
{
        // Build TCP server
        led_wifi_conn.type  = ESPCONN_TCP;
        led_wifi_conn.state = ESPCONN_NONE;
        led_wifi_conn.proto.tcp = &led_wifi_tcp;
        led_wifi_conn.proto.tcp->local_port = WIFI_SERVER_PORT;

        espconn_regist_connectcb(&led_wifi_conn,led_wifi_connect_callback);
        espconn_accept(&led_wifi_conn);
        // Set TCP alive 1800s
        espconn_regist_time(&led_wifi_conn,WIFI_TCP_TIME,1);
}

//
// Check if need disconnect TCP connect
// 此函数在一个任务中周期性调用,用来断开上一个连接
void LEDWifiProc(void)
{
        sint8 ret;
        if (0) {
                os_printf("LEDWifiProc = 0x%xn",(unsigned int)laster_wifi_conn);
                ret = espconn_disconnect(laster_wifi_conn);
                os_printf("disconnect ret = %dn",ret);
                ret = espconn_delete(laster_wifi_conn);
                os_printf("delete ret = %dn",ret);
                laster_wifi_conn = current_wifi_conn;
                led_tcp_dis = 0;
        }
}

sint8 led_wifi_send_data(uint8 *data,unsigned short len)
{
        if (data == NULL || len == 0)
                return -1;
      
        return espconn_send(&led_wifi_conn,data,len);
}

void IRAM_ATTR led_wifi_event_handle(System_Event_t *event)
{
        os_printf("led_wifi_event_handle evt = %dn",event->event_id);
}

void led_wifi_init(void)
{
        unsigned int ret;
        struct softap_config cfg;

        led_tcp_dis = 0;

        // WIFI mode init
        wifi_set_opmode(STATIONAP_MODE);

      
        // Set WIFI default name and password
        wifi_softap_get_config(&cfg);

        // Load device name save in flash
        // When new device,the softAP authmode will OPEN ?
        if (cfg.authmode != AUTH_WPA_WPA2_PSK || cfg.max_connection != 1) {
                sprintf(cfg.ssid,"%s",WIFI_DEFAULT_SSID);
                sprintf(cfg.password,"%s",WIFI_DEFAULT_PASSWD);      
        }
        cfg.authmode       = AUTH_WPA_WPA2_PSK;
        cfg.ssid_len       = 0;
        cfg.max_connection = 1;
        wifi_softap_set_config(&cfg);

        // wifi_set_event_handler_cb(led_wifi_event_handle);

        led_wifi_build_tcp();

        laster_wifi_conn  = &led_wifi_conn;
        current_wifi_conn = &led_wifi_conn;
        os_printf("led_wifi_conn = 0x%xn",(unsigned int)&led_wifi_conn);
}

串口打印LOG如下:
SDK version:1.3.0(68c9e7b)
led_wifi_conn = 0x3fff044c
mode : sta(5c:cf:7f:12:65:42) + softAP(5e:cf:7f:12:65:42)
add if0
dhcp server start:(ip:192.168.4.1,mask:255.255.255.0,gw:192.168.4.1)
add if1
bcn 100
add 1
aid 1
station: 68:3e:34:61:d5:61 join, AID = 1
NOT the same
led_wifi_connect_callback
conn->link_cnt = 0
conn->state = 3
current_wifi_conn = 0x3fffde20
espconn_server_close, close
NOT the same
led_wifi_connect_callback
conn->link_cnt = 1
conn->state = 3
current_wifi_conn = 0x3fffdcb0
espconn_server_close, close
NOT the same
led_wifi_connect_callback
conn->link_cnt = 2
conn->state = 3
current_wifi_conn = 0x3fffdd78
espconn_server_close, close
NOT the same
led_wifi_connect_callback
conn->link_cnt = 3
conn->state = 3
current_wifi_conn = 0x3fffdf58
espconn_server_close, close
NOT the same
led_wifi_connect_callback
conn->link_cnt = 4
conn->state = 3
current_wifi_conn = 0x3fffdf28
espconn_server_close, close


当conn->link_cnt = 4后,再也不能连接,不管LEDWifiProc有没有执行disconnect,都没用

回帖(1)

费加罗

2024-7-22 17:17:19
从您提供的代码片段来看,您正在尝试使用ESP8266作为TCP服务器,并希望在手机应用重复连接时断开之前的连接。然而,您遇到的问题是在达到5个连接后,ESP8266无法再接受新的连接。这里我会提供一些建议和解决方案,以帮助您解决这个问题。

1. 确保ESP8266固件支持多个TCP连接。ESP8266的某些固件版本可能不支持多个TCP连接。请确保您使用的固件版本支持多个TCP连接。

2. 检查TCP连接的监听和接受。在ESP8266上设置TCP服务器时,需要确保正确监听和接受TCP连接。以下是使用ESP8266非OS SDK的示例代码:

```c
#include "espconn.h"

static espconn server;

void ICACHE_FLASH_ATTR
esp8266_init_tcp_server(void)
{
    server.type = ESPCONN_TCP;
    server.state = ESPCONN_NONE;
    espconn_regist_connectcb(&server, tcp_client_connect_callback);
    espconn_regist_reconcb(&server, tcp_client_reconnect_callback);
    espconn_regist_disconcb(&server, tcp_client_disconnect_callback);
    espconn_accept(&server);
}

void ICACHE_FLASH_ATTR
tcp_client_connect_callback(void *arg)
{
    espconn *pespconn = (espconn *)arg;
    // 处理新连接
}

void ICACHE_FLASH_ATTR
tcp_client_reconnect_callback(void *arg, sint8 err)
{
    // 处理重连
}

void ICACHE_FLASH_ATTR
tcp_client_disconnect_callback(void *arg)
{
    espconn *pespconn = (espconn *)arg;
    espconn_disconnect(pespconn);
}
```

3. 断开连接时释放资源。在ESP8266上断开TCP连接时,需要确保释放所有相关资源。以下是断开连接的示例代码:

```c
void ICACHE_FLASH_ATTR
disconnect_client(espconn *pespconn)
{
    espconn_disconnect(pespconn);
    espconn_delete(pespconn);
}
```

4. 限制最大连接数。您可以设置一个全局变量来限制最大连接数,当达到最大连接数时,拒绝新的连接请求。以下是一个示例:

```c
#define MAX_CONNECTIONS 5

static uint8_t connection_count = 0;

void ICACHE_FLASH_ATTR
tcp_client_connect_callback(void *arg)
{
    if (connection_count >= MAX_CONNECTIONS)
    {
        // 拒绝新连接
        return;
    }

    espconn *pespconn = (espconn *)arg;
    connection_count++;
    // 处理新连接
}

void ICACHE_FLASH_ATTR
tcp_client_disconnect_callback(void *arg)
{
    espconn *pespconn = (espconn *)arg;
    connection_count--;
    espconn_disconnect(pespconn);
}
```

5. 检查内存泄漏。确保在断开连接时释放所有分配的内存,以避免内存泄漏。

6. 使用ESP8266的RTOS SDK。如果您使用的是非OS SDK,建议您尝试使用ESP8266的RTOS SDK,它提供了更丰富的API和更好的性能。

希望这些建议能帮助您解决问题。如果问题仍然存在,请提供更多代码和详细信息,以便我们能够更好地帮助您。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分