【Unable to create TCP socket: errno 23 “ 错误分析】

Unable to create TCP socket: errno 23 " 错误分析

一、问题描述

硬件:ESP32
IDF 版本: V4.3
应用场景是做一个智能手写笔,需求是持续创建并关闭 UDP socket 以及 TCP socket ,UDP 接受广播包的监听服务,目的是获取TCP 服务端的IP地址和端口号,TCP连接成功后,发送自定义TCP长连接包,创建过程中会出现 “ Unable to create TCP socket: errno 23 ” 错误。

二、问题分析

" errno 23 " 代表的是 open many open files in system, 也就是说创建 SOCKET 的个数超过了最大 socket 限制数,目前 idf menuconfig 中 socket 个数最大可以支持到 16 个,默认是 10 个。

代码中有调用 close 接口去关闭 TCP socket ,但是 TCP 关闭有四次握手的过程,会有一个TIME_WAIT 的等待时间,也就是 2MSL 的时间,这个时间最长可以达到 2min, 所以调用 close 接口并不是立即就能关闭掉的。

三、解决方案

通过 setsockopt 接口设置 SO_LINGER 来调整 TCP 关闭时间。
So_linger的作用
struct linger {
int l_onoff; // 0 = off, nozero = on
int l_linger; // linger time
};
其取值和处理如下:
1)设置 l_onoff为0,则该选项关闭,l_linger的值被忽略,等于内核缺省情况,close调用会立即返回给调用者,如果可能将会传输任何未发送的数据;
2)设置 l_onoff !=0 && l_linger = 0,则套接口关闭时TCP夭折连接,TCP将丢弃保留在套接口发送缓冲区中的任何数据并发送一个RST给对方,而不是通常的四分组终止序列,这避免了TIME_WAIT状态;
3)设置 l_onoff != 0 && l_linger != 0,当套接口关闭时内核将拖延一段时间(由l_linger决定)。
如果套接口缓冲区中仍残留数据,进程将处于睡眠状态,直到
(a)所有数据发送完且被对方确认,之后进行正常的终止序列(描述字访问计数为0)
或(b)延迟时间到。
此种情况下,应用程序检查close的返回值是非常重要的,如果在数据发送完并被确认前时间到,close将返回EWOULDBLOCK错误且套接口发送缓冲区中的任何数据都丢失。

idf 下面解决步骤:
1) menuconfig 中 enable so_linger 选项。
idf.py menuconfig—>Component config–>LWIP—>[*]Enable SO_LINGER processing
在这里插入图片描述
2)添加如下代码:

linger link ;
link.on_off = 1 ;
link.linger = 0 ;
setsockopt(m_sockConnect, SOL_SOCKET, SO_LINGER, (const char*)&link, sizeof(linger));
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值