完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
idf版本:V5.0.2
开发板:esp-32 问题描述: 我使用两台esp32,不断重复以下步骤:连接wifi--》创建TCP server --》作为TCP client向另一台esp32发送数据 --》 断开 wifi 经过五轮左右循环后出现以下两个报错:Code: Select all TCP SERVER: Unable to create socket: errno 23 TCP client: Unable to create socket: errno 23 TCP client与TCP server 具体代码如下:Code: Select all /** * @brief 发送 wifi 数据, wifi 发送数据指令格式: * |-- 目的地址长度(1 byte) --|-- 目的地址(n bytes) --|-- 信息长度(2 bytes) --|-- 目的地址长度(n bytes) --| * @param[in] data - 发送数据内容 * @param[in] len - 发送数据内容的长度 */int tcpClientSendDataToRemote(uint8_t *data, const uint16_t len){ char host_ip[17] = {0}; int addr_family = 0; int ip_protocol = 0; int sendDataLen = 0; int toWrite = len; int written = 0; int sock = 0; int err = 0; if (NULL == data || len < 11 || WifiStation.status != WIFI_STATUS_CONNECTED) { return -1; } memcpy((uint8_t *)host_ip, (uint8_t *)(data + 1), data[0]); struct sockaddr_in dest_addr; dest_addr.sin_addr.s_addr = inet_addr(host_ip); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(PORT); addr_family = AF_INET; ip_protocol = IPPROTO_IP; sock = socket(addr_family, SOCK_STREAM, ip_protocol); if (sock < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); goto failed; } ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT); struct timeval timeout; timeout.tv_sec = 5; timeout.tv_usec = 0; err = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); if (err != 0) { goto failed; } err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6)); if (err != 0) { ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno); goto failed; } ESP_LOGI(TAG, "Successfully connected"); // struct linger link; // link.l_onoff = 1; // link.l_linger = 5; // err = setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(struct linger)); // if (err != 0) // { // ESP_LOGE(TAG, "SO_LINGER errno %d", errno); // goto failed; // } while (toWrite > 0) { // written = send(sock, (data + 1 + data[0] + 2 + (sendDataLen - toWrite)), toWrite, 0); written = send(sock, (data + len - toWrite), toWrite, 0); if (written < 0) { ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno); goto failed; } toWrite -= written; } if (sock != -1) { ESP_LOGW(TAG, "Shutting down socket"); printf("************ %s(%d) sock:%dn", __func__, __LINE__, sock); shutdown(sock, 0); // struct linger link; // link.l_onoff = 1; // link.l_linger = 5; // setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(struct linger)); close(sock); printf("************ %s(%d) sock:%dn", __func__, __LINE__, sock); } return 0;failed: if (sock != -1) { printf("************ %s(%d) sock:%dn", __func__, __LINE__, sock); shutdown(sock, 0); // struct linger link; // link.l_onoff = 1; // link.l_linger = 5; // setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(struct linger)); close(sock); printf("************ %s(%d) sock:%dn", __func__, __LINE__, sock); } return -1;}/** * @brief wifi 接收任务 */static void tcpServeTask(void *pvParameters){ char addr_str[128]; int addr_family = (int)pvParameters; int ip_protocol = 0; int keepAlive = 1; int keepIdle = KEEPALIVE_IDLE; int keepInterval = KEEPALIVE_INTERVAL; int keepCount = KEEPALIVE_COUNT; struct sockaddr_storage dest_addr; int err = 0; if (addr_family == AF_INET) { struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr; dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY); dest_addr_ip4->sin_family = AF_INET; dest_addr_ip4->sin_port = htons(PORT); ip_protocol = IPPROTO_IP; } listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol); if (listen_sock < 0) { ESP_LOGE(SERVER_TAG, "Unable to create socket: errno %d", errno); goto CLEAN_UP; } int opt = 1; setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); ESP_LOGI(SERVER_TAG, "Socket created"); err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (err != 0) { ESP_LOGE(SERVER_TAG, "Socket unable to bind: errno %d", errno); ESP_LOGE(SERVER_TAG, "IPPROTO: %d", addr_family); goto CLEAN_UP; } ESP_LOGI(SERVER_TAG, "Socket bound, port %d", PORT); struct linger link; link.l_onoff = 1; link.l_linger = 5; err = setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(struct linger)); if (err != 0) { ESP_LOGE(SERVER_TAG, "SO_LINGER errno: %d", errno); goto CLEAN_UP; } ESP_LOGI(SERVER_TAG, "Start listen"); err = listen(listen_sock, 1); if (err != 0) { ESP_LOGE(SERVER_TAG, "Error occurred during listen: errno %d", errno); goto CLEAN_UP; } while (1) { ESP_LOGI(SERVER_TAG, "Socket listening"); struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6 socklen_t addr_len = sizeof(source_addr); int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len); if (sock < 0) { ESP_LOGE(SERVER_TAG, "Unable to accept connection: errno %d", errno); goto CLEAN_UP; } // Set tcp keepalive option setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int)); setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int)); setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int)); setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int)); // Convert ip address to string if (source_addr.ss_family == PF_INET) { inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1); } ESP_LOGI(SERVER_TAG, "Socket accepted ip address: %s", addr_str); do_retransmit(sock); shutdown(sock, 0); // struct linger link; // link.l_onoff = 1; // link.l_linger = 5; // setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(struct linger)); close(sock); }CLEAN_UP: printf("************ %s(%d) listen_sock:%dn", __func__, __LINE__, listen_sock); close(listen_sock); TcpServerHandle = NULL; vTaskDelete(NULL); printf("************ %s(%d) listen_sock:%dn", __func__, __LINE__, listen_sock);}void tcpServeTaskStartUp(void){ tcpServeTaskStop(); xTaskCreate(tcpServeTask, "TCP_CLIENT_TASK", 8192, (void*)AF_INET, 5, &TcpServerHandle);}void tcpServeTaskStop(void){ if (TcpServerHandle != NULL) { vTaskDelete(TcpServerHandle); TcpServerHandle = NULL; } if (listen_sock > 0) { printf("************ %s(%d) listen_sock:%dn", __func__, __LINE__, listen_sock); close(listen_sock); printf("************ %s(%d) listen_sock:%dn", __func__, __LINE__, listen_sock); listen_sock = 0; }} 通过打印,发现socket没有释放,于是menuconfig TCP参数,减小MSL时间,将socket数量提高到16,但依然会出现无法分配socket问题Code: Select all (16) Maximum active TCP Connections(16) Maximum listening TCP Connections TCP high speed retransmissions(12) Maximum number of retransmissions of data segments(12) Maximum number of retransmissions of SYN segments(1440) Maximum Segment Size (MSS)(250) TCP timer interval(ms)(6000) Maximum segment lifetime (MSL)(2000) Maximum FIN segment lifetime(5744) Default send buffer size(5744) Default receive window size(6) Default TCP receive mail box size Queue incoming out-of-order segments[ ] Support sending selective acknowledgements Pre-allocate transmit PBUF size (MSS) --->(1500) Default TCP rto time 问题描述较长,麻烦好心人提供帮助,谢谢! |
|
相关推荐
1个回答
|
|
根据您提供的问题描述和代码,您在使用ESP32进行WiFi连接、创建TCP服务器和客户端以及发送数据的过程中遇到了无法创建socket的问题。这个问题可能是由于资源耗尽或错误配置导致的。以下是一些建议和解决方案:
1. **检查内存使用情况**:ESP32的内存有限,如果在循环过程中没有正确释放资源,可能会导致内存耗尽。您可以使用`esp_get_free_heap_size()`函数检查内存使用情况,并在循环结束后释放不再使用的资源。 2. **检查错误处理**:在您的代码中,如果遇到错误,您应该添加适当的错误处理逻辑。例如,当创建socket失败时,您可以打印错误信息并尝试重新创建socket。 3. **使用非阻塞socket**:在ESP32上,使用非阻塞socket可以避免在等待网络操作完成时阻塞整个程序。您可以使用`socket()`函数创建非阻塞socket,然后在需要时使用`select()`函数检查socket状态。 4. **优化TCP连接管理**:在您的代码中,您可能需要优化TCP连接的管理。例如,当TCP连接建立后,您可以使用`accept()`函数接受连接,然后在新的socket上进行数据传输。在数据传输完成后,确保关闭socket并释放资源。 5. **检查WiFi连接稳定性**:在您的循环过程中,WiFi连接可能会受到干扰或断开。您可以使用`esp_wifi_connect()`函数检查WiFi连接状态,并在需要时重新连接。 6. **更新ESP-IDF版本**:您当前使用的ESP-IDF版本是V5.0.2,可能存在一些已知的问题或限制。建议您尝试升级到最新版本的ESP-IDF,以获取最新的功能和修复。 7. **查看ESP-IDF文档和示例**:ESP-IDF提供了丰富的文档和示例代码,您可以查阅相关文档和示例,了解如何正确使用ESP32的网络功能。 8. **使用ESP-IDF的调试功能**:ESP-IDF提供了调试功能,您可以使用这些功能来跟踪程序的执行过程,找出问题所在。 |
|
|
|
只有小组成员才能发言,加入小组>>
313 浏览 0 评论
1170 浏览 1 评论
586浏览 6评论
483浏览 5评论
有没有办法在不使用混杂模式的情况下实现Wifi驱动程序接收缓冲区访问中断呢?
468浏览 5评论
467浏览 4评论
442浏览 4评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 16:05 , Processed in 1.676257 second(s), Total 82, Slave 65 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号