如何在Linux上使用C语言检测端口是否已被占用?

4

我正在编写一个简单的Web服务器。我想让用户设置服务器监听的端口,但是我该如何知道用户输入的端口是否已经被占用?(如果我知道它已经被占用,我可以告诉他们输入另一个端口。)

5个回答

9
只需尝试绑定端口,如果失败,请检查errno中的EADDRINUSE。这是唯一的方法,因为要正确进行任何此类检查必须是原子的。如果您进行了单独的检查,然后在发现它未被使用后尝试绑定到端口,则另一个进程可能会在介入时间内绑定到该端口,从而再次导致失败。同样,如果您进行了单独的检查并发现端口已被占用,则正在使用它的进程可能会在介入时间内关闭端口、退出或崩溃,从而再次使结果不正确。
所有这些的重点(我写长篇答案而不是简短答案的原因)是正确、强大的方式来检查“我能做什么?”几乎总是尝试去做,然后检查失败。任何其他方法都可能导致竞争条件,在许多情况下,竞争条件(虽然可能不是您的情况)是安全漏洞。

5

bind()会失败:

成功时返回零。发生错误时,返回-1,并适当设置errno。

EADDRINUSE 给定地址已经在使用中。


但是用这种方式,我必须创建一个服务器套接字...绑定()...然后关闭它...有更简单的方法吗? - wong2
2
不,那是唯一正确的方法。你为什么要关闭它呢?如果你已经绑定了它,就简单地用它来进行监听 - 你无法知道它是否仍然可用,因为另一个进程可能会在此期间绑定到该端口。 - ThiefMaster
@wong2:请看我的回答。除非你绑定端口并保持绑定状态直到准备使用它,否则无法确定你的问题(“端口是否已被使用?”)的答案而不可能出错。提前检查(然后释放它)可能会得出错误的答案。 - R.. GitHub STOP HELPING ICE

0
另一种方法:尝试连接到本地主机上的该端口。

1
加入一些这是个坏主意的原因以及这个测试可能失败的方式,你的答案就会更有价值。 - R.. GitHub STOP HELPING ICE
1
a) 运行的服务器可以监听特定的接口,而与“localhost”的连接不会检查它;b) 超时;c) 我使用这种方法来检查端口以启动TCP服务器作为单独的进程(它在失败时没有返回正确的错误代码,所以这是唯一的检查方式)。 - khachik
顺便提一下,即使您通过绑定端口进行原子测试,(a)也是一个问题。 即使您成功在0.0.0.0:port上建立连接,某些其他进程可能已经绑定了aaa.bbb.ccc.ddd:port(外部网络地址的IP)。 - R.. GitHub STOP HELPING ICE
这只是一条评论,而不是对问题的答案。请使用“添加评论”为作者留下反馈。 - Rostyslav Dzinko
@RostyslavDzinko,这个回答解决了如何检查端口是否繁忙的问题,为什么它应该在评论中呢? - khachik
我完全理解为什么Wong不想使用bind() - 如果你正在进行监控和定期检查,你不想冒险在进程重新启动时意外占用端口。 - user1279741

0

如果bind()显示出错


0
只需创建一个socket并调用bind()。如果bind()成功,则继续执行listen(),否则您应该执行一些错误处理过程,例如切换到默认端口,打印错误消息并等待用户互动,或者至少记录并退出。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接