Erlang OTP管理器gen_tcp-{错误,eaddrinuse}

Erlang OTP管理器gen_tcp-{错误,eaddrinuse},erlang,restart,otp,erlang-supervisor,gen-tcp,Erlang,Restart,Otp,Erlang Supervisor,Gen Tcp,我无法理解在崩溃的gen_tcp:listen线程中添加一个管理器如何实际重启该工作线程。因为崩溃会使我想听的端口暂时失效。当崩溃发生并且我试图手动重新启动我的应用程序时,我收到“{error,eaddrinuse}”。我还没有为这个工人实施任何监管,因为我不知道它会如何工作 如何重新启动gen_tcp:listen?管理gen_tcp套接字的进程是gen_服务器吗?如果是这样,你的生活会更轻松 如果它是gen\u服务器,则将进程\u标志(trap\u exit,true)添加到init函数中。

我无法理解在崩溃的gen_tcp:listen线程中添加一个管理器如何实际重启该工作线程。因为崩溃会使我想听的端口暂时失效。当崩溃发生并且我试图手动重新启动我的应用程序时,我收到“{error,eaddrinuse}”。我还没有为这个工人实施任何监管,因为我不知道它会如何工作


如何重新启动gen_tcp:listen?

管理gen_tcp套接字的进程是gen_服务器吗?如果是这样,你的生活会更轻松

如果它是gen\u服务器,则将
进程\u标志(trap\u exit,true)
添加到init函数中。这使得当进程“崩溃”时,它在实际退出进程之前调用
terminate/2
回调函数。使用此方法,您可以在terminate函数中手动关闭侦听套接字,从而避免恼人的端口清理延迟


如果您不使用gen_服务器,同样的原则仍然适用,但您必须更明确地捕获错误。

在大多数情况下,由于侦听套接字链接到控制进程(创建它的进程),此进程的终止将很好地关闭套接字,并允许您在同一端口上再次侦听


对于所有其他情况,您应该将
{reuseaddr,true}
选项传递给
gen\u tcp:listen/2
。事实上,应用程序的侦听套接字在崩溃后会短暂保持活动状态,此选项允许您在此期间重用该地址。

或者,您也可以在与“接受者”不同的进程中启动侦听套接字。所述过程除了充当套接字的存储之外,不应该做任何事情,从而确保它永远不会崩溃。这是因为可以从多个进程同时调用
gen\u tcp:accept
。感谢您的快速回复!我将尝试添加一个陷阱,因为我正在运行gen_服务器(应该提到这一点)。关于拆分接受/侦听-如果我的应用程序崩溃,这真的足够吗?如果整个应用程序崩溃,那么即使您拆分了责任,您也会遇到同样的问题。但是,如果只在您真正需要的地方指定trap_exit,并允许您的客户端进程在适当的时候正常崩溃,您仍然会从中受益。另外,一定要看看ranch(),它可以为您处理很多这方面的事情。reuseaddr的用途与您建议的不同。它可能确实可以达到这个目的,但如果使用不当,也可能会产生严重的副作用。reuseaddr正是阻止OP的原因,对于不可修补的崩溃是必需的。ranch也使用此选项。reuseaddr的目的是允许服务器重新使用已经使用过的端口,是的,但有更好的方法来解决此特定问题,即在终止时正确清理侦听套接字,ranch也这样做。reuseaddr的更好用途是用于管理数千个短期客户机的大容量服务器。实际上,我相信在大多数情况下都会进行适当的清理,而不会捕获出口,而OP确实需要reuseaddr。我不相信ranch陷阱可以正确清理侦听套接字。没错,ranch不使用它(双重检查源代码)。这就是说,只要没有挂起的连接,适当的清理确实可以防止“已经在使用”的问题,因此在这种情况下会对他有所帮助。就我而言,我将reuseaddr选项与同名的系统级TCP选项混为一谈,这在全局范围内允许重用等待时间端口,并可能造成问题。作为一种监听选项,它被广泛用于重新建立异常关闭套接字(例如崩溃)的监听服务器。有时,即使套接字已关闭,端口仍在使用一段时间。不知道为什么。@rvirding-显然是在套接字上有挂起的连接的情况下。如果没有挂起的连接,它应该立即进入关闭状态。Alexander-请参阅Paul关于reuseaddr使用的回答,即使我的回答有帮助,它也应该用于您的服务器。