[JAVA] Créez une application de chat avec WebSocket (Tyrus) + libGDX + Kotlin

introduction

J'ai créé une application de chat très simple en utilisant WebSocket.

supposition

Tyrus version 1.13 Kotlin 1.0.5 libGDX 1.9.5

Project Tyrus

Project Tyrus est RI (implémentation de référence) de JSR 356 - API Java pour WebSocket. Project Tyrus

Préparation à l'utilisation

Pour utiliser Project Tyrus, il est nécessaire d'ajouter une dépendance. Ajoutez les deux suivants.

compile group: 'org.glassfish.tyrus', name: 'tyrus-container-grizzly-server', version: tyrusVersion
compile group: 'org.glassfish.tyrus', name: 'tyrus-server', version: tyrusVersion

J'ai fait une compilation gradle et j'ai confirmé que les fichiers JAR suivants avaient été déposés dans le référentiel local.

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

À propos, grizzly est un framework de serveur Web également utilisé dans Glassfish. Tyrus lui-même semble être traité comme un sous-projet de poisson-verre.

Project Grizzly

Comment utiliser Tyrus (côté serveur)

Utiliser Tyrus est très simple.

Implémentation du point de terminaison du serveur

Une implémentation basée sur des annotations est fournie pour l'implémentation du point de terminaison du serveur, nous allons donc l'utiliser.

Plus précisément, le mappage d'URL est effectué avec @ServerEndpoint et le traitement des événements de cycle de vie est implémenté lorsque la communication WebSocket est reçue par le serveur avec @OnOpen, @OnMessage, @OnClose et @OnError, respectivement.


@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}Entré dans la pièce")
        }
    }

    @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 + "A quitté la salle")
        }
    }

    @OnError
    fun onError(session: Session, t: Throwable) {
        println("server-[error] " + session)
    }
}

Dans cette implémentation, la session utilisateur est mise en cache et diffusée dans CopyOnWriteArraySet, mais si vous souhaitez la concevoir correctement, il est préférable d'utiliser Redis ou DB au lieu de la mémoire Java. Je ne l'ai pas essayé, mais il semble possible d'enregistrer une classe qui hérite de javax.websocket.Endpoint en tant qu'implémentation de point de terminaison de serveur.

Implémentation de la logique de démarrage du serveur

Ensuite, créez simplement une instance de serveur et démarrez-la, et le serveur intégré démarrera. Le point de terminaison du serveur WebSocket enregistré sera inactif.

object Main {
    @JvmStatic fun main(args: Array<String>) {
        val server = Server("localhost",/*Hôte de connexion*/ 8181,/*Port*/,
                            "/ws" /*Racine de contexte*/,mapOf(),/*Propriétés des paramètres*/
                             ServerEndPoint::class.java/*Point de terminaison du serveur*/
                            )
        try {
            server.start()
            System.`in`.read()
        } finally {
            server.stop()
        }
    }
}

server.start () se déploiera sur le conteneur Tyrus. Si vous accédez à localhost: 8181 (en utilisant ce code comme exemple), vous devriez voir que le serveur est opérationnel.

Ceci termine l'implémentation de WebSocket côté serveur. Tout ce que vous avez à faire est de préparer un client et de communiquer avec WebSocket.

Comment utiliser Tyrus (côté client)

JavaScript est souvent vu dans les implémentations de client WebSocket.


ws = new WebSocket('ws://localhost:8181/ws/chat/' + guestId);
ws.onmessage = function(e) {
    //Processus de dessin lorsqu'un message arrive
};

ws.send("Processus d'envoi de message");

Ce n'est pas mal du tout de l'implémenter en JavaScript, mais Tyrus a une API (Java) pour l'implémentation client. J'ai décidé de l'utiliser aussi parce que c'était un gros problème.

Implémentation du point de terminaison client

La méthode de mise en œuvre du point de terminaison client est fondamentalement la même que la mise en œuvre du point de terminaison du serveur. Une annotation est disponible, alors utilisez-la.

Je ne l'ai pas essayé, mais il semble possible d'enregistrer une classe qui hérite de javax.websocket.Endpoint en tant qu'implémentation de point de terminaison client.

@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 {
            //* Le texte est un composant personnalisé pour afficher du texte
                        //Les coordonnées Y sont décalées pour que les textes soient alignés.
            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")
    }
}

Appel du point de terminaison client

Une classe appelée ClientManager est préparée pour appeler le client, alors utilisez-la.

val client = ClientManager.createClient()
client.run {
    asyncConnectToServer(clientEndpoint, URI("ws://localhost:8181/ws/chat/${text}"))
}

Cela se connectera au serveur WebSocket. Si vous souhaitez envoyer un message au serveur:

session.asyncRemote.sendText(text)

demo

out.gif

Code source

https://github.com/yyYank/chatppoimono

URL de référence

http://backpaper0.github.io/2013/07/14/websocket.html http://backpaper0.github.io/2013/07/15/websocket_pathparam.html

Recommended Posts

Créez une application de chat avec WebSocket (Tyrus) + libGDX + Kotlin
[Rails6] Créer une nouvelle application avec Rails [Débutant]
J'ai créé une application Janken avec kotlin
[Rails 5] Créer une nouvelle application avec Rails [Débutant]
Créez une application de recherche simple avec Spring Boot
Créez une discussion d'équipe avec Rails Action Cable
Entraînez-vous à créer une application de chat simple avec Docker + Sinatra
J'ai créé une application de chat.
Créez un terrain de jeu avec Xcode 12
[Rails] J'ai essayé de créer une mini application avec FullCalendar
Créez une application Web Hello World avec Spring Framework + Jetty
Créez un environnement Vue3 avec Docker!
Créez une application mémo avec Tomcat + JSP + Servlet + MySQL à l'aide d'Eclipse
Créez une application avec Spring Boot 2
Créer une application de minuterie avec de la boue
Créer une nouvelle application avec Rails
Créez une application avec Spring Boot
Créer une application en ligne de commande avec maven
Essayez de créer une application client serveur
Créez des exceptions avec une interface fluide
Créez une application de recherche de restaurant avec l'API IBM Watson + Guru Navi (avec source)
[Kotlin / Android] Créer une vue personnalisée
Créez un projet de développement d'application Spring Boot avec la commande cURL + tar
Créez une application de résumé de nouvelles techniques de style LINEnews avec Rails x LineBot! [Partie 1]
Créez un fichier jar avec la commande
Créez un lot à la demande simple avec Spring Batch
[Retrait des rails] Créez une fonction de retrait simple avec des rails
Créer un graphique à barres simple avec MPAndroidChart
Créer une application TODO dans Java 7 Créer un en-tête
Créez une classe temporaire avec le nouvel Object () {}
J'ai créé une application Janken avec Android
Créez un site Web avec Spring Boot + Gradle (jdk1.8.x)
[Memo] Créez facilement un environnement CentOS 8 avec Docker
Créer un CSR avec des informations étendues en Java
[Rails] rails nouveau pour créer une base de données avec PostgreSQL
[Windows] [IntelliJ] [Java] [Tomcat] Créer un environnement pour Tomcat 9 avec IntelliJ
Créons un processus chronométré avec la minuterie de Java! !!
Créer une application Kotlin à l'aide du conteneur OpenJDK Docker
[Java] Créer une collection avec un seul élément
J'ai essayé de créer une application de clonage LINE
Créer un compte SandBox avec IP Fastlane Spaces
Créer une carte multi-touches avec une bibliothèque standard
Créer un serveur API Web avec Spring Boot
Créer un environnement de développement Spring Boot avec docker