错误:在将套接字与地址绑定时地址已在使用中,但端口号由“netstat”免费显示
Posted
技术标签:
【中文标题】错误:在将套接字与地址绑定时地址已在使用中,但端口号由“netstat”免费显示【英文标题】:Error: Address already in use while binding socket with address but the port number is shown free by `netstat` 【发布时间】:2011-07-03 15:54:05 【问题描述】:我尝试将我的套接字(服务器套接字)绑定到端口号8000
。它为我工作并完成了工作。在代码的末尾,我也关闭了套接字。下一刻我再次运行我的代码,它告诉我地址已经在使用中。我已经打印了错误值strerror(errno);
的含义,以查看我的代码是否在每个点都正常工作。为了检查端口是否空闲,我使用netstat
检查了它,但它显示端口号8000
是空闲的。它发生在我身上很多次。每次我再等几秒钟,然后它又开始工作了。我正在使用c语言。那么他是什么原因导致我的操作系统出现这种行为。
几秒钟后,我运行代码,然后它就可以工作了。
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ sudo ./a.out
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1348/lighttpd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 984/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1131/cupsd
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1211/mysqld
tcp6 0 0 :::22 :::* LISTEN 984/sshd
tcp6 0 0 ::1:631 :::* LISTEN 1131/cupsd
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ sudo ./a.out
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
anirudh@anirudh-Aspire-5920:~/Desktop/testing$
【问题讨论】:
您是否还仔细关闭了在服务器运行时与服务器建立的所有连接? 【参考方案1】:我也遇到了同样的问题。这是因为您正在关闭与套接字的连接,而不是套接字本身。 socket 可以进入 TIME_WAIT 状态(确保所有数据都已传输,如果可能,TCP 保证交付)and take up to 4 minutes to release。
或者,对于真正详细/技术性的解释,check this link
这当然很烦人,但这不是错误。关于SO_REUSEADDR
的使用,请参阅@Vereb 对此答案的评论。
【讨论】:
在您链接的页面上有一个可能的解决方案。您可以对套接字使用 SO_REUSEADDR 选项。在此处查看 setsockopt:linux.die.net/man/3/setsockopt【参考方案2】:试试这样的 netstat:netstat -ntp
,没有-l
。它将显示 tcp 连接
TIME_WAIT
状态。
【讨论】:
【参考方案3】:只需输入
unlink [SOCKET NAME]
在终端中,那么错误应该不再存在。
【讨论】:
那是 Unix 域套接字。问题是关于 TCP 套接字的。【参考方案4】:即使icfantv对这个问题的回答已经很完美了,我在测试中还有更多的发现。
作为一个处于监听状态的服务器套接字,如果它只是处于监听状态,它甚至接受来自客户端的请求和获取数据,但没有任何数据发送动作。我们仍然可以在服务器停止后立即重新启动服务器。但是如果在服务器端向客户端发送任何数据的动作,相同的服务(相同的端口)重启会出现这个错误:(地址已在使用中)。
我认为这是由 TCP/IP 设计原则造成的。当服务器将数据发送回客户端时,它必须确保数据发送成功,为了做到这一点,操作系统(Linux)需要监视连接,即使服务器应用程序关闭了这个套接字。 但我仍然相信内核套接字设计器可以改善这个问题。
【讨论】:
【参考方案5】:我知道这个问题已经有一段时间了,但我找到了解决方案:
int sockfd;
int option = 1;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
这使套接字能够立即被重用。
如果这是“错误的”,我深表歉意。我对套接字不是很有经验
【讨论】:
我喜欢你将wrong
放在引号中的方式,暗示任何不同意你的人都是错误的。
引号更像是“如果它有效,那就没有错”之类的东西。我意识到这可能不是首选方式,如果有人知道“正确”的方式,我会很感兴趣。
1 是什么意思?
这是不久前的事情,所以如果我错了请纠正我,但我相信这是因为当你希望套接字不逗留时,它必须是“非零”。我找不到任何具体的内容,但您可以在以下位置阅读更多信息:ibm.com/support/knowledgecenter/en/SSB23S_1.1.0.15/gtpc2/…【参考方案6】:
我收到的错误是:
cockpit.socket: Failed to listen on sockets: Address already in use
我发现的解决方法是:
-
我不得不禁用 selinux
在 /usr/lib/systemd/system/cockpit 服务中,我更改了 行:
#ExecStartPre=/usr/sbin/remotectl certificate --ensure --user=root --group=cockpit-ws --selinux-type=etc_t
到:
#ExecStartPre=/usr/sbin/remotectl certificate --ensure --user=root --group=cockpit-ws
所以你可以看到我拿出了关于 selinux 的论点 然后我跑了:
systemctl daemon-reload
systemctl start cockpit.service
然后我浏览到:
我接受了自签名证书并且是 能够成功登录驾驶舱并正常使用。
这一切都在 Fedora25 机器上。 9090 端口已经
使用firewall-cmd
添加
【讨论】:
【参考方案7】:如前所述,您的套接字可能进入TIME_WAIT
状态。 Thomas A. Fine here 很好地描述了这个问题。
总结一下,socket关闭流程如下图:
托马斯 说:
看上图,很明显
TIME_WAIT
可以 如果远端启动关闭,则避免。所以服务器可以 通过让客户端先关闭来避免问题。应用程序 必须设计协议,以便客户端知道何时关闭。这 服务器可以安全地关闭以响应来自客户端的 EOF,但是 它还需要在期望 EOF 时设置超时,以防万一 客户端不优雅地离开了网络。在很多情况下只是 在服务器关闭前等待几秒钟就足够了。
互联网上通常建议使用SO_REUSEADDR
,但Thomas添加:
奇怪的是,使用
SO_REUSEADDR
实际上会导致更难的“地址” 已在使用”错误。SO_REUSADDR
允许您使用 卡在TIME_WAIT
,但您仍然无法使用该端口建立一个 连接到它连接的最后一个地方。什么?假设我选 本地1010端口,连接foobar.com的300端口,然后关闭 在本地,将该端口留在TIME_WAIT
。我可以重用本地端口 1010 立即连接到除foobar.com
300 端口以外的任何地方。
【讨论】:
【参考方案8】:对于 AF_UNIX,您可以使用 call unlink (path);在“服务器”应用程序中的 close() 套接字之后
【讨论】:
以上是关于错误:在将套接字与地址绑定时地址已在使用中,但端口号由“netstat”免费显示的主要内容,如果未能解决你的问题,请参考以下文章
Ruby on Rails - 地址已在使用中 - 为“0.0.0.0”端口 3000 (Errno::EADDRINUSE) 绑定 (2)