每次创建新服务器实例时生成一个随机端口号

Generate a random port numbers everytime a new server instance is created

我正在尝试创建一个目前 运行 在本地主机上的 Ktor 服务器。当我 运行 终端上只有一个服务器实例时它工作正常,但是当我在终端上打开一个新选项卡并且 运行 同一服务器的另一个实例时,我得到这个 Warning/Error:

Exception in thread "main" java.net.BindException: Address already in use
        at sun.nio.ch.Net.bind0(Native Method)
        at sun.nio.ch.Net.bind(Net.java:461)
        at sun.nio.ch.Net.bind(Net.java:453)
        at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:222)
        at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:134)
        at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:562)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1334)
        at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:506)
        at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:491)
        at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:973)
        at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:260)
        at io.netty.bootstrap.AbstractBootstrap.run(AbstractBootstrap.java:356)
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
        at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989)
        at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
        at io.ktor.server.netty.EventLoopGroupProxy$Companion$create$factory.run(NettyApplicationEngine.kt:241)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.lang.Thread.run(Thread.java:748)

发生这种情况是因为服务器正在使用已在使用的端口。

我想要实现的是,服务器应该自动为第二个实例生成一个唯一的端口号。我不确定如何在 Ktor 上执行此操作。

这是我服务器的当前配置:

fun main() {
    val env = applicationEngineEnvironment {
        module {
            main()
        }
        connector {
            host = "localhost"
            port = 8080
        }

    }
    embeddedServer(Netty, env).start(true)
}

您可以使用ServerSocket自动分配端口号并关闭该套接字。这是一个例子:

import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.application.*
import io.ktor.response.*
import io.ktor.routing.*
import java.net.ServerSocket

fun main(args: Array<String>) {
    embeddedServer(Netty, port = getFreePort()) {
        routing {
            get("/") {
                call.respondText { "Hello" }
            }
        }
    }.start()
}

fun getFreePort(): Int {
    val socket = ServerSocket(0)
    val port = socket.localPort
    socket.close()
    return port
}

此外,还有一个feature request开箱即用的分配随机端口号的活动。