【问题标题】:socket not released after service restart服务重启后套接字未释放
【发布时间】:2012-12-13 16:30:39
【问题描述】:

有: A:持有打开套接字的程序 B:看门狗脚本作为服务运行:

while true
do
        if [ -z "`pidofproc $1`" ]; then
                $1;
            chrt -f -p 40 `pidofproc $1`
                sleep 8
        fi;
        sleep 2
done

服务何时开始 - 看门狗开始
当服务停止时 - 看门狗和程序被杀死(killall)。

现在程序要升级自己,所以它调用system( "upgrade.sh" );

升级.sh:

/sbin/service watchdog stop

.... install upgrade  .....

exec /sbin/service watchdog start &

升级成功,但程序启动时 - 无法打开套接字(已在使用中) - 出现此错误 - 程序退出(由看门狗重新启动)。

lsof -i 显示端口上的三个程序:

watchdog

program

sleep

程序和睡眠 pid 总是会改变(即退出/重启行为)

看门狗 pid 持久。

我试图用

替换system(...)

if(!fork()) exec(...) ,但同样的问题仍然存在。

【问题讨论】:

  • 如果你展示了试图打开套接字的代码而不是一些完全不相关的脚本,那将会更加有用......作为一个疯狂的猜测,我会说你应该阅读关于 SO_REUSEADDR
  • 在套接字创建中没有 SO_REUSEADDR。我想保持这种方式。为什么socket没有释放?
  • 有acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), ec); acceptor_.set_option(boost::asio::ip::tcp::no_delay(true), ec); acceptor_.set_option(boost::asio::socket_base::linger(true, 200), ec);

标签: c++ linux sockets service restart


【解决方案1】:

根据关闭后重新启动的速度,套接字将徘徊。默认情况下,Linux 会在套接字释放后(通过close() 或进程终止时)将套接字标记为正在使用,以确保传入的连接尝试或由于网络延迟而延迟的数据不会t 最终出现在错误的应用程序中。

这必须在应用程序中修复。需要设置SO_REUSEADDR sockopt。根据 socket(7) 的手册页:

表示用于验证提供的地址的规则 在 bind(2) 调用中应该允许重用本地地址。为了 AF_INET sockets 这意味着一个socket可以绑定,除非当 有一个活动的侦听套接字绑定到该地址。什么时候 监听套接字绑定到具有特定端口的 INADDR_ANY 那么任何本地都无法绑定到此端口 地址。参数是一个整数布尔标志。

这必须在创建套接字后使用setsockopt 进行设置。

【讨论】:

  • 所以如果我不想使用 SO_REUSEADDR,我应该在升级脚本中添加 sleep 60
猜你喜欢
  • 2015-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多