socket返回值为0的问题排查
背景知识:
LTE中,eNB和MME之间通过s1ap协议交流,而s1ap的底层协议为sctp。因此s1链路的建立,要依赖于sctp底层链路的建立。需要配置的sctp参数包括:
本地ip、本地端口号、远端ip、远端端口号、心跳间隔、最大路径重传次数、INIT最大重传次数、输入输出流个数等。
而建立socket是sctp建立连接的先决条件,我们使用的时socket函数创建的套接字:
int socket_id = int socket(int af, int type, int protocol);
问题现象
将配置发送给sctp链路管理模块,触发sctp的建立。但是日志显示,利用socket建立的socket_id为0。
通过在网上查阅了一些文章,发现socket建立的时候,socket_id是0,1,2的基本属于标准输入输出套接字标识。通常用户自己创建的socket不会出现这个问题。
问题原因
socket_id为0,1,2的虽然是给标准输入输出用的,但是如果我们close(0)之后,该socket_id = 0的便处于“空闲”状态。用户利用socket函数创建套接字时,便会讲0分配给新创建的socket。
经过查找close函数使用的地方,最终定位到了一处:
1、该模块上下文初始化时,全被初始化为了0,该上下文结构体如下:
typedef struct _wireshark_global_contxt_t
{
....
s32 udp_sock_id;
...
} wireshark_global_context_t;
2、该模块初始化时,会建立初始socket连接
该模块建立socket连接时,只允许建立一个连接,因此为了防止存在多个连接的情况,在调用socket函数创建socket之前,加入了如下判断
if (wiresahrk_gl_ctx.udp_sock_id >= 0)
{
close(wireshark_gl_ctx.udp_sock_id);
wireshark_gl_ctx.udp_sock_id = INVALID_SOCKET; # INVALID_SOCKET = -1
}
于是就出现了close(0)的情况。
问题解决
1、上下文初始化时,将udp_sock_id初始化为非法值(-1)
2、close() socket连接的时候,判断条件为>0的情况下close