当 tcp 客户端与我的 TCP 服务器建立 tcp 连接时,在它发送了几个数据包后,我想对此 TCP 连接进行硬/中止关闭,如何在 linux C 中做到这一点?
这里的硬/中止关闭意味着 tcp 服务器将立即向客户端发送 RST。根本没有FIN/ACK。
谢谢!
当 tcp 客户端与我的 TCP 服务器建立 tcp 连接时,在它发送了几个数据包后,我想对此 TCP 连接进行硬/中止关闭,如何在 linux C 中做到这一点?
这里的硬/中止关闭意味着 tcp 服务器将立即向客户端发送 RST。根本没有FIN/ACK。
谢谢!
SO_LINGER 设置或获取 SO_LINGER 选项。论点是一个逗留的结构。
struct linger {
int l_onoff; /* linger active */
int l_linger; /* how many seconds to linger for */
};
启用后,在成功发送套接字的所有排队消息或达到延迟超时之前,关闭(2)或关闭(2)将不会返回。否则,调用立即返回并在后台完成关闭。当套接字作为 exit(2) 的一部分关闭时,它总是在后台徘徊。
另一个设置:
setsockopt(..., SO_LINGER,...) 的效果取决于 linger 结构(传递给 setsockopt() 的第三个参数)中的值是什么:
情况1:linger->l_onoff 为零(linger->l_linger 没有意义):这是默认的。
在 close() 上,底层堆栈在确保发送所有未发送的数据后尝试正常关闭连接。在 TCP 等面向连接的协议的情况下,堆栈还确保发送的数据得到对等方的确认。堆栈将在后台执行上述优雅关闭(在调用 close() 返回之后),无论套接字是阻塞还是非阻塞。
情况 2: linger->l_onoff 非零且 linger->l_linger 为零:
close() 立即返回。底层堆栈丢弃任何未发送的数据,并且在面向连接的协议(如 TCP)的情况下,向对等方发送 RST(重置)(这称为硬关闭或中止关闭)。对等方应用程序对 read()/recv() 数据的所有后续尝试都将导致 ECONNRESET。
情况 3:linger->l_onoff 非零且 linger->l_linger 非零:
close() 将阻塞(如果是阻塞套接字)或因 EWOULDBLOCK 失败(如果非阻塞),直到正常关闭完成或 linger->l_linger 中指定的时间过去(超时)。超时后,堆栈的行为与上述情况 2 相同。
您应该将 SO_LINGER 套接字选项设置为超时 0 并调用 close()。如果有任何待发送的数据将丢失,则发送 RST 而不是 FIN。