考虑一个父进程完成 a socket/bind/accept
,并将分叉子进程,并打开该套接字以供它们进行通信,同时父进程继续接受连接。然后该父进程被终止。
现在,另一个进程尝试在同一端口上绑定到父进程绑定到的同一地址,但收到 EADDRINUSE 错误。
但是,当您使用 完成此过程时sshd
,似乎sshd
是能够重新绑定到已关闭的端口,而在重新启动窗口期间(sshd 父进程未运行),不同的程序(以不同用户身份运行)只会获取 EADDRINUSE。
这背后的语义是什么?为什么可以sshd
重新绑定,但另一个用户进程却不能?
此外,我可以确认netstat -a | grep PORT
只有子进程运行期间(当其他进程不能运行时bind
)的输出,唯一的连接是ESTABLISHED
一个,没有处于LISTEN
状态。
答案1
虽然我不理解所有的语义(我要么找错地方,要么缺少文档),但我相信在关闭连接后的一定时间内(可能由 设定SO_LINGER
),没有进程可以打开一个具有相同详细信息的新套接字,除非它们已SO_REUSEADDR
设置。
据我了解,这是为了防止有人在连接关闭后重新连接,并且该进程必须处理用于前一个进程的数据包。
man 7 socket
没有记录这一点,SO_REUSEADDR
这使得这个答案很难弄清楚。