I created a very simple chat app using WebSocket.
Tyrus version 1.13 Kotlin 1.0.5 libGDX 1.9.5
Project Tyrus
Project Tyrus is an RI (reference implementation) of JSR 356 --Java API for WebSocket. Project Tyrus
In order to use Project Tyrus, it is necessary to add dependency. Add the following two.
compile group: 'org.glassfish.tyrus', name: 'tyrus-container-grizzly-server', version: tyrusVersion
compile group: 'org.glassfish.tyrus', name: 'tyrus-server', version: tyrusVersion
I did a gradle build and confirmed that the following jars were dropped in the local repository.
org.glassfish.grizzly:grizzly-framework:2.3.25
org.glassfish.grizzly:grizzly-http:2.3.25
org.glassfish.grizzly:grizzly-http-server:2.3.25
org.glassfish.tyrus:tyrus-client:1.13
org.glassfish.tyrus:tyrus-container-grizzly-client:1.13
org.glassfish.tyrus:tyrus-container-grizzly-server:1.13
org.glassfish.tyrus:tyrus-core:1.13
org.glassfish.tyrus:tyrus-server:1.13
org.glassfish.tyrus:tyrus-spi:1.13
About, grizzly is a web server framework that is also used in glassfish. Tyrus itself seems to be treated as a subproject of glassfish.
Using Tyrus is very easy.
Annotation-based implementation is provided for the server endpoint implementation, so use that.
Specifically, URL mapping is performed with @ServerEndpoint, and life cycle event processing is implemented when WebSocket communication is received by the server with @OnOpen, @OnMessage, @OnClose, and @OnError respectively.
@ServerEndpoint("/chat/{guest-id}")
class ServerEndPoint {
    companion object {
        private val sessions = CopyOnWriteArraySet<Session>()
    }
    @OnOpen
    fun onOpen(@PathParam("guest-id") guestId: String, session: Session) {
        println("server-[open] $guestId")
        sessions.add(session)
        for (s in sessions) {
            s.asyncRemote.sendText("${guestId}Entered the room")
        }
    }
    @OnMessage
    fun onMessage(@PathParam("guest-id") guestId: String, message: String, session: Session) {
        println("server-[message][$message] $session")
        // broadcast
        for (s in sessions) {
            println("requestURI" + s.requestURI.toString())
            s.asyncRemote.sendText("[$guestId] $message")
        }
    }
    @OnClose
    fun onClose(@PathParam("guest-id") guestId: String, session: Session) {
        println("server-[close] " + session)
        sessions.remove(session)
        // broadcast
        for (s in sessions) {
            s.asyncRemote.sendText(guestId + "Has left the room")
        }
    }
    @OnError
    fun onError(session: Session, t: Throwable) {
        println("server-[error] " + session)
    }
}
In this implementation, the user session is cached and broadcast in CopyOnWriteArraySet, but if you want to design properly, it is better to use Redis or DB instead of Java memory. I haven't tried it, but it seems possible to register a class that inherits javax.websocket.Endpoint as a server endpoint implementation.
Then, just create a server instance and start it, and the embedded server will start. The registered WebSocket server endpoint will be idle.
object Main {
    @JvmStatic fun main(args: Array<String>) {
        val server = Server("localhost",/*Connection host*/ 8181,/*port*/,
                            "/ws" /*Context root*/,mapOf(),/*Settings properties*/
                             ServerEndPoint::class.java/*Server endpoint*/
                            )
        try {
            server.start()
            System.`in`.read()
        } finally {
            server.stop()
        }
    }
}
server.start () will deploy to the Tyrus container. If you go to localhost: 8181 (using this code as an example), you'll see that the server is up.
This completes the server-side WebSocket implementation. All you have to do is prepare a client and communicate with WebSocket.
JavaScript is often seen in WebSocket client implementations.
ws = new WebSocket('ws://localhost:8181/ws/chat/' + guestId);
ws.onmessage = function(e) {
    //Drawing process when a message comes
};
ws.send("Message sending process");
It's not bad to implement it in JavaScript at all, but Tyrus has an API (Java's) for client implementation. I decided to use this as well because it was a big deal.
The implementation method of the client endpoint is basically the same as the implementation of the server endpoint. Annotation-based ones are available, so use that.
I haven't tried it, but it seems possible to register a class that inherits javax.websocket.Endpoint as a client endpoint implementation.
@javax.websocket.ClientEndpoint
class ClientEndpoint(val stage: Stage, val scene: ChatScene) {
    val defaultOffsetY = 490
    val offsetY = AtomicInteger(defaultOffsetY)
    val textHeight = 22
    @OnOpen
    fun onOpen(session: Session, config: EndpointConfig) {
        println("client-[open] " + session)
        scene.session = session
    }
    @OnMessage
    fun onMessage(message: String, session: Session) {
        scene.session = session
        println("client-[message][$message] $session")
        println("----------")
        Gdx.app.postRunnable {
            //* Text is a self-made component for displaying text.
                        //The Y coordinates are shifted so that the texts are lined up.
            val textObject = Text(message, 20, Position(0f, offsetY.addAndGet(-textHeight).toFloat()))
            textObject.let {
                it.setPosition(0f, 0f)
                stage.addActor(it)
            }
        }
    }
    @OnClose
    fun onClose(session: Session) {
        println("client-[close] $session")
    }
    @OnError
    fun onError(session: Session?, t: Throwable?) {
        println("client-[error] ${t?.message} $session")
    }
}
A class called ClientManager is prepared for calling the client, so use it.
val client = ClientManager.createClient()
client.run {
    asyncConnectToServer(clientEndpoint, URI("ws://localhost:8181/ws/chat/${text}"))
}
This will connect to the WebSocket server. If you want to send a message to the server:
session.asyncRemote.sendText(text)
demo

https://github.com/yyYank/chatppoimono
http://backpaper0.github.io/2013/07/14/websocket.html http://backpaper0.github.io/2013/07/15/websocket_pathparam.html
Recommended Posts