c - 如果接口丢失了 IP 地址,close() 不会关闭 tcp 连接
问题描述
当 linux box 失去其 DHCP IP 地址租约时,我的程序建立了 tcp 连接。之后它会尝试关闭连接,因此当 dhcp 服务器恢复时,它将再次重新建立 tcp 连接。它使用SO_REUSEADDR。我确实读过这个http://hea-www.harvard.edu/~fine/Tech/addrinuse.html但在这个应用程序中重用地址是一个要求。我重现此问题的方法是发出ifconfig etho 0.0.0.0
但是,close(sockfd)的结果是不可预测的。有时它会正确关闭套接字。有时netstat -ant连续显示 tcp 0 0 192.168.1.119:54322 192.168.1.41:54321 (STATE) 其中(STATE)可以是ESTABLISHED或FIN_WAIT1或CLOSE_WAIT之一。
最初我的代码刚刚关闭()。在网上阅读了多个资源后,我尝试了一些建议。
首先我尝试了这个(基于http://deepix.github.io/2016/10/21/tcprst.html)
if (sockFd != -1) {
linger lin;
lin.l_onoff = 1;
lin.l_linger = 0;
if (setsockopt(sockFd, SOL_SOCKET, SO_LINGER, (const char *)&lin, sizeof(linger)) == -1) {
std::cout << "Error setting socket opt SO_LINGER while trying to close " << std::endl;
}
close(sockFd);
}
它没有帮助,所以我尝试了这个(基于close() 没有正确关闭套接字)
bool haveInput(int fd, double timeout) {
int status;
fd_set fds;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = (long)timeout; // cast needed for C++
tv.tv_usec = (long)((timeout - tv.tv_sec) * 1000000); // 'suseconds_t'
while (1) {
if (!(status = select(fd + 1, &fds, 0, 0, &tv)))
return FALSE;
else if (status > 0 && FD_ISSET(fd, &fds))
return TRUE;
else if (status > 0)
break;
else if (errno != EINTR)
break;
}
}
void myClose(int sockFd)
{
if (sockFd != -1) {
int err = 1;
socklen_t len = sizeof err;
getsockopt(sockFd, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
shutdown(sockFd, SHUT_WR);
usleep(20000);
char discard[99];
while (haveInput(sockFd, 0.01))
if (!read(sockFd, discard, sizeof discard))
break;
shutdown(sockFd, SHUT_RD);
usleep(20000);
close(sockFd);
sockFd = -1;
}
}
和以前一样,有时它会关闭连接,有时它不会。我知道在这种情况下,另一方既不能发送FIN也不能发送ACK,因此无法正常关闭。
在这种情况下,有没有一种可靠的方法可以完全关闭 tcp 连接?
谢谢
解决方案
推荐阅读
- laravel - 如何在 Laravel 中重定向到支付成功的页面
- angular - 访问组件的特定实例(已编辑)
- javascript - 制作我的第一个网页,陷入“未捕获的 ReferenceError:未定义要求”错误
- kotlin - 如何使用箭头的类型类?
- web - “保证”不上传到服务器的网络应用程序?
- idl-programming-language - 我的 IDL 循环只保存最后一次迭代 - 我该如何修复它?
- laravel - 在 hasMany() 中使用 Eloquent 指定更复杂的条件
- java - 是什么导致我在尝试创建对象时遇到错误?
- javascript - 函数参数的 JavaScript 绑定
- python - Windows-curses 安装在 ubuntu 上