Tcl 是否有其他方法查找未使用的端口号

Tcl 是否有其他方法查找未使用的端口号,tcl,Tcl,我需要运行一个用Tcl编写的web服务器,默认情况下,它依赖于一个硬编码的端口号进行侦听,尽管我担心如果该端口已经在使用,它可能会导致失败。它确实允许您将端口号作为参数传递,但如果您不确定它是未使用的端口,则可能会导致相同的问题 我设计了以下方法来获得一个未使用的端口,它似乎可以工作(见下一行),并且失败的可能性(即,该端口在中间时间内被使用)似乎比仅仅依靠随机选择的端口号要小得多。尽管如此,我还是不完全满意,我想知道还有什么其他方法可以实现这个目标 proc noop {chan addr p

我需要运行一个用Tcl编写的web服务器,默认情况下,它依赖于一个硬编码的端口号进行侦听,尽管我担心如果该端口已经在使用,它可能会导致失败。它确实允许您将端口号作为参数传递,但如果您不确定它是未使用的端口,则可能会导致相同的问题

我设计了以下方法来获得一个未使用的端口,它似乎可以工作(见下一行),并且失败的可能性(即,该端口在中间时间内被使用)似乎比仅仅依靠随机选择的端口号要小得多。尽管如此,我还是不完全满意,我想知道还有什么其他方法可以实现这个目标

proc noop {chan addr port} {
}
set chan [socket -server noop 0]
set sockname [chan configure $chan -sockname]
chan close $chan
set port [lindex $sockname end]         ;# e.g. 51922
set chan2 [socket -server noop $port]   ;# test re-usability of port
chan close $chan2

实际上,您所能做的并不多,因为从理论上讲,当您自己不打开套接字,但不在临时端口范围内(即从32768(0x8000)到65535(0xFFFF)的端口)时,套接字可以在任何时候打开将有帮助,因为这样您就不会遇到为TCP连接的客户端自动分配端口的问题

作为普通用户运行的本地Web服务器的端口号通常为8000和8080(HTTPS为8443),尽管实际端口号通常无关紧要。关键是,您通常将这些端口规划为机器总体规划的一部分;你可以有一个很好的想法,没有任何东西会干扰,因为你可以控制系统。虚拟机使这一切变得更加简单(在完全部署场景中,您可以使用apache或nginx代理将所有内容显示在受系统保护的端口80和443后面)


或者,让实际系统打开伪端口0(如脚本中所示),然后报告实际分配的端口,然后继续为该端口提供实际服务。这是对您现在所做工作的一个微不足道的扩展…在一个级别上,但需要为非常量端口号设置整个系统。这可能很困难,而且通常只对测试框架有用(Tcl自己的测试套件经常使用这个技巧)或者底层协议是从头开始设计的,以这种方式工作。

从理论上讲,套接字在任何时候都可以打开,而不是自己打开,但不在临时端口范围内(即从32768(0x8000)到65535(0xFFFF)的端口)将有帮助,因为这样您就不会遇到为TCP连接的客户端自动分配端口的问题

作为普通用户运行的本地Web服务器的端口号通常为8000和8080(HTTPS为8443),尽管实际端口号通常无关紧要。关键是,您通常将这些端口规划为机器总体规划的一部分;你可以有一个很好的想法,没有任何东西会干扰,因为你可以控制系统。虚拟机使这一切变得更加简单(在完全部署场景中,您可以使用apache或nginx代理将所有内容显示在受系统保护的端口80和443后面)


或者,让实际系统打开伪端口0(如脚本中所示),然后报告实际分配的端口,然后继续为该端口提供实际服务。这是对您现在所做工作的一个微不足道的扩展…在一个级别上,但需要为非常量端口号设置整个系统。这可能很困难,通常只对测试框架有用(Tcl自己的测试套件经常使用这一技巧),或者底层协议是从头开始设计的。我写这个软件是为了在其他人的机器上运行,所以我不知道他们可能使用或不使用什么端口。然而,我将修改服务器的源代码(无论如何,它是我自己的git fork),并应用第三段中的方法,至于非常量端口号,我计划将其输出到一个临时文件中。根据我所读到的(可能我误解了),另一个策略可能是在第一段中使用
SO_REUSEPORT
,sentinel
socket-server
调用,然后在嗅探端口后第二次调用
socket-server
,以真正为端口服务。SO_REUSEPORT的好处是,除非显式关闭,否则sentinal套接字将保持绑定状态,并避免任何可能的争用情况。唉,从脚本级别来看,
socket-server-reuseport 1
仅在Tcl 8.7 IIRC上可用。我编写这个软件是为了在其他人的机器上运行,所以我不知道他们可能使用或不使用什么端口。然而,我将修改服务器的源代码(无论如何,它是我自己的git fork),并应用第三段中的方法,至于非常量端口号,我计划将其输出到一个临时文件中。根据我所读到的(可能我误解了),另一个策略可能是在第一段中使用
SO_REUSEPORT
,sentinel
socket-server
调用,然后在嗅探端口后第二次调用
socket-server
,以真正为端口服务。SO_REUSEPORT的好处是,除非显式关闭,否则sentinal套接字将保持绑定状态,并避免任何可能的争用情况。唉,从脚本级别来看,
socket-server-reuseport 1
仅在Tcl 8.7 IIRC上可用。