我试图在连接上强制重置TCP。 建议的方法是将SO_LINGER设置为0并将调用设置为close()。
我正是这样做的,但连接仍处于ESTABLISHED状态。 套接字以非阻塞模式运行。操作系统是Raspbian。
代码:
struct linger l;
l.l_onoff = 1;
l.l_linger = 0;
if (setsockopt(server->connection_socket, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) != 0) {
LOG_E(tcp, "setting SO_LINGER failed");
}
if (close(server->connection_socket) != 0) {
LOG_E(tcp, "closing socket failed");
}
server->connection_socket = 0;
LOG_I(tcp, "current TCP connection was closed");
Wireshark跟踪也没有显示RST。
应用程序的其他任何线程都没有在该套接字上执行任何操作。
我无法弄清楚出了什么问题,我们非常感谢任何建议。
解决
问题是文件描述符泄露给通过system()
调用创建的子项。
事实上,当我列出所有带有lsof -i tcp
的TCP套接字描述符时,我发现子进程已经从父进程打开了文件描述符(即使父进程已经没有)。
解决方案是请求在分叉进程中关闭文件描述符(在accept()
之后)。
fcntl(server->connection_socket, F_SETFD, FD_CLOEXEC)
答案 0 :(得分:1)
在您调用close
后,您无法再发送和接收数据。此外,在close
调用之后,仅当套接字描述符的引用计数器变为0时才会发送RST。然后连接进入CLOSED
状态,并且丢弃接收和发送缓冲区中的数据。 />
可能答案在于你如何分叉一个过程(正如EJP在评论中提到的那样)。在调用fork
之后,您似乎没有在父进程中关闭已接受的套接字。因此套接字引用计数器非零,并且在close
之后没有RST
史蒂文斯在UNIX网络编程中很好地描述了这种情况。