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

Posted

技术标签:

【中文标题】每次创建新的服务器实例时生成一个随机端口号【英文标题】:Generate a random port numbers everytime a new server instance is created 【发布时间】:2021-08-05 21:08:43 【问题描述】:

我正在尝试创建一个当前在 localhost 上运行的 Ktor 服务器。当我在终端上仅运行一个服务器实例时,它工作正常,但是当我在终端上打开一个新选项卡并运行同一服务器的另一个实例时,我收到此警告/错误:

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$2.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$4.run(SingleThreadEventExecutor.java:989)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.ktor.server.netty.EventLoopGroupProxy$Companion$create$factory$1$1.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)

【问题讨论】:

为什么要同时运行 2 个实例 @AnaniyaJemberu 那是因为我正在尝试开发一个需要多个实例同时运行的实时消息传递网络。 使用 websocket 然后@iLoveYou3000 @AnaniyaJemberu 任何示例将不胜感激 ktor.io/docs/creating-web-socket-chat.html 【参考方案1】:

您可以使用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 可以直接分配随机端口号。

【讨论】:

有没有一种方法可以检查,如果当前端口号已经在使用中,那么我们生成一个随机的 4 位端口号并将这个新生成的端口号分配给创建的新服务器实例? 我假设 ServerSocket(0) 为我做这件事。

以上是关于每次创建新的服务器实例时生成一个随机端口号的主要内容,如果未能解决你的问题,请参考以下文章

阿里云怎样使用云服务器开放端口号

为什么TCPUDP套接字服务器端需要绑定端口号客户端不需要?

网络编程2

Spring Cloud 端口号,让选择更智能

Windows 技术篇 - 通过注册表修改远程桌面连接的端口号实例演示

如何使用端口号删除 docker 容器