Andrey Gromov
05/30/2019, 3:26 PMprivate suspend fun eventLoop(port: Int) {
val server = aSocket(ActorSelectorManager(<http://Dispatchers.IO|Dispatchers.IO>))
.udp()
.bind(InetSocketAddress(port)) <<<<<<<<<<< Exception
I'm sure that port is free on bind moment
Stacktrace
Exception in thread "main" java.net.SocketException: Already bound
at java.base/sun.nio.ch.Net.translateToSocketException(Net.java:164)
at java.base/sun.nio.ch.DatagramSocketAdaptor.bind(DatagramSocketAdaptor.java:105)
at io.ktor.network.sockets.UDPSocketBuilder.bind(Builders.kt:152)
at io.ktor.network.sockets.UDPSocketBuilder.bind$default(Builders.kt:143)
at co.fun.multiplayer.udp.ServerListener.eventLoop(ServerListener.kt:34)
at co.fun.multiplayer.udp.ServerListener$start$1.invokeSuspend(ServerListener.kt:26)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:238)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.kt:116)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:80)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at co.fun.multiplayer.udp.ServerListener.start(ServerListener.kt:25)
at co.fun.multiplayer.udp.MainKt.main(Main.kt:14)
Caused by: java.nio.channels.AlreadyBoundException
at java.base/sun.nio.ch.DatagramChannelImpl.bind(DatagramChannelImpl.java:784)
at java.base/sun.nio.ch.DatagramSocketAdaptor.bind(DatagramSocketAdaptor.java:103)
... 14 more
This workaround helping, but it is very ugly
var server: BoundDatagramSocket
while (true) {
try {
server = aSocket(ActorSelectorManager(<http://Dispatchers.IO|Dispatchers.IO>))
.udp()
.bind(InetSocketAddress(port))
break
} catch (e: Exception) {
}
}
cy
05/30/2019, 3:34 PMAndrey Gromov
05/30/2019, 3:51 PMAndrey Gromov
05/30/2019, 3:52 PMDico
05/30/2019, 4:10 PMcy
05/30/2019, 4:12 PMcy
05/30/2019, 4:13 PMAndrey Gromov
05/30/2019, 4:30 PMcy
05/30/2019, 4:31 PMcy
05/30/2019, 4:31 PMAndrey Gromov
05/30/2019, 4:35 PMnetstat -a
does not contains used portAndrey Gromov
05/30/2019, 4:39 PMAndrey Gromov
05/30/2019, 4:46 PMrunBlocking {
arrayOf(5002, 5010, 5011, 5012).forEach { launch { eventLoop(it) } }
}
private suspend fun eventLoop(port: Int) {
var server: BoundDatagramSocket
while (true) {
try {
server = aSocket(ActorSelectorManager(<http://Dispatchers.IO|Dispatchers.IO>))
.udp()
.bind(InetSocketAddress(port))
break
} catch (e: Exception) {
println("Oops!")
}
}
println("Each! $port")
.....
Output:
Oops!
Each! 5002 <<< This is original port
Exception in thread "DefaultDispatcher-worker-3" java.nio.channels.ClosedChannelException
at java.base/java.nio.channels.spi.AbstractSelectableChannel.register(AbstractSelectableChannel.java:206)
at io.ktor.network.selector.SelectorManagerSupport.applyInterest(SelectorManagerSupport.kt:116)
at io.ktor.network.selector.ActorSelectorManager.process(ActorSelectorManager.kt:87)
at io.ktor.network.selector.ActorSelectorManager$process$1.invokeSuspend(ActorSelectorManager.kt)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at io.ktor.network.selector.ActorSelectorManager$ContinuationHolder.resume(ActorSelectorManager.kt:187)
at io.ktor.network.selector.ActorSelectorManager.publishInterest(ActorSelectorManager.kt:141)
at io.ktor.network.selector.SelectorManagerSupport.select(SelectorManagerSupport.kt:46)
at io.ktor.network.sockets.DatagramSocketImpl.receiveSuspend(DatagramSocketImpl.kt:70)
at io.ktor.network.sockets.DatagramSocketImpl.receiveImpl(DatagramSocketImpl.kt:59)
at io.ktor.network.sockets.DatagramSocketImpl$receiver$1.invokeSuspend(DatagramSocketImpl.kt:36)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:238)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Oops!
Each! 5010
Oops!
Oops!
Oops!
Each! 5011
Each! 5012
cy
05/30/2019, 4:49 PMprintln("Oops $port ${Thread.currentThread().name}!")
Andrey Gromov
05/31/2019, 6:13 AM> Task :MainKt.main()
Oops! 5002 main!
Oops! 5002 main!
Oops! 5002 main!
Oops! 5002 main!
Oops! 5002 main!
Oops! 5002 main!
Oops! 5002 main!
Oops! 5002 main!
Oops! 5002 main!
Oops! 5002 main!
Oops! 5002 main!
Each! 5002 main!
Each! 5010 main!
Oops! 5011 main!
Each! 5011 main!
Oops! 5012 main!
Oops! 5012 main!
Oops! 5012 main!
Oops! 5012 main!
Oops! 5012 main!
Each! 5012 main!
Andrey Gromov
05/31/2019, 6:27 AMlaunch(<http://Dispatchers.IO|Dispatchers.IO>)
- exceptions frequency dramatically reduced, but do not removed at all.
launch(<http://Dispatcher.IO|Dispatcher.IO>){eventLoop(5002)}
arrayOf(5010,5011,5012).forEach{
launch{eventLoop(it)}
}
Note that I use IO only for first binding call.
Each! 5002 DefaultDispatcher-worker-2!
Oops! 5010 main!
Each! 5010 main!
Each! 5011 main!
Each! 5012 main!
If I use IO
for all bindings - problem does not appears.Andrey Gromov
05/31/2019, 7:11 AMaSocket(ActorSelectorManager(<http://Dispatchers.IO|Dispatchers.IO>))
does not affectscy
05/31/2019, 9:25 AMAndrey Gromov
05/31/2019, 9:49 AMinline fun <C : Closeable, R> SelectorManager.buildOrClose(create: SelectorProvider.() -> C, setup: C.() -> R): R {
while (true) {
val result = create(provider)
try {
return setup(result)
} catch (t: Throwable) {
result.close() <<<<<<<<<<<<<<<
throw t
}
}
}
Andrey Gromov
05/31/2019, 10:10 AM@Override
public DatagramChannel bind(SocketAddress local) throws IOException {
readLock.lock();
try {
writeLock.lock();
try {
synchronized (stateLock) {
ensureOpen();
if (localAddress != null)
throw new AlreadyBoundException();
bindInternal(local);
}
} finally {
writeLock.unlock();
}
} finally {
readLock.unlock();
}
return this;
}
localAddress = /0:0:0:0:0:0:0:0:62107
Andrey Gromov
06/04/2019, 9:07 AM