![当没有绑定侦听套接字但连接已打开时获取 EADDRINUSE 的语义是什么](https://linux22.com/image/57524/%E5%BD%93%E6%B2%A1%E6%9C%89%E7%BB%91%E5%AE%9A%E4%BE%A6%E5%90%AC%E5%A5%97%E6%8E%A5%E5%AD%97%E4%BD%86%E8%BF%9E%E6%8E%A5%E5%B7%B2%E6%89%93%E5%BC%80%E6%97%B6%E8%8E%B7%E5%8F%96%20EADDRINUSE%20%E7%9A%84%E8%AF%AD%E4%B9%89%E6%98%AF%E4%BB%80%E4%B9%88.png)
考虑一个父进程完成 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
这使得这个答案很难弄清楚。