[JAVA] Erstellen Sie eine Chat-App mit WebSocket (Tyrus) + libGDX + Kotlin

Einführung

Ich habe mit WebSocket eine sehr einfache Chat-App erstellt.

Annahme

Tyrus version 1.13 Kotlin 1.0.5 libGDX 1.9.5

Project Tyrus

Project Tyrus ist RI (Referenzimplementierung) der JSR 356 - Java API für WebSocket. Project Tyrus

Vorbereitung zur Verwendung

Um Project Tyrus verwenden zu können, muss eine Abhängigkeit hinzugefügt werden. Fügen Sie die folgenden zwei hinzu.

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

Ich habe einen Gradle-Build durchgeführt und bestätigt, dass die folgenden Gläser im lokalen Repository abgelegt wurden.

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

Grizzly ist ein Webserver-Framework, das auch in Glassfish verwendet wird. Tyrus selbst scheint als Teilprojekt von Glasfischen behandelt zu werden.

Project Grizzly

Verwendung von Tyrus (Serverseite)

Die Verwendung von Tyrus ist sehr einfach.

Implementierung des Serverendpunkts

Für die Server-Endpunkt-Implementierung wird eine auf Anmerkungen basierende Implementierung bereitgestellt, die wir daher verwenden werden.

Insbesondere wird die URL-Zuordnung mit @ServerEndpoint durchgeführt, und die Verarbeitung von Lebenszyklusereignissen wird implementiert, wenn der Server WebSocket-Kommunikation mit @OnOpen, @OnMessage, @OnClose bzw. @OnError empfängt.


@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}Betrat den Raum")
        }
    }

    @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 + "Hat den Raum verlassen")
        }
    }

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

In dieser Implementierung wird die Benutzersitzung zwischengespeichert und in CopyOnWriteArraySet gesendet. Wenn Sie sie jedoch ordnungsgemäß entwerfen möchten, ist es besser, Redis oder DB anstelle von Java-Speicher zu verwenden. Ich habe es nicht ausprobiert, aber es scheint möglich zu sein, eine Klasse, die javax.websocket.Endpoint erbt, als Serverendpunktimplementierung zu registrieren.

Implementierung der Serverstartlogik

Erstellen Sie dann einfach eine Serverinstanz und starten Sie sie. Der integrierte Server wird gestartet. Der registrierte WebSocket-Serverendpunkt ist inaktiv.

object Main {
    @JvmStatic fun main(args: Array<String>) {
        val server = Server("localhost",/*Verbindungshost*/ 8181,/*Hafen*/,
                            "/ws" /*Kontextstamm*/,mapOf(),/*Einstellungen Eigenschaften*/
                             ServerEndPoint::class.java/*Serverendpunkt*/
                            )
        try {
            server.start()
            System.`in`.read()
        } finally {
            server.stop()
        }
    }
}

server.start () wird im Tyrus-Container bereitgestellt. Wenn Sie auf localhost: 8181 zugreifen (anhand dieses Codes als Beispiel), sollten Sie feststellen, dass der Server aktiv ist.

Damit ist die serverseitige WebSocket-Implementierung abgeschlossen. Sie müssen lediglich einen Client vorbereiten und mit WebSocket kommunizieren.

Verwendung von Tyrus (Client-Seite)

JavaScript wird häufig in WebSocket-Client-Implementierungen verwendet.


ws = new WebSocket('ws://localhost:8181/ws/chat/' + guestId);
ws.onmessage = function(e) {
    //Zeichenvorgang, wenn eine Nachricht kommt
};

ws.send("Prozess zum Senden von Nachrichten");

Es ist nicht schlecht, es in JavaScript zu implementieren, aber Tyrus hat eine API (Java) für die Client-Implementierung. Ich habe mich auch dafür entschieden, weil es eine große Sache war.

Implementierung des Client-Endpunkts

Die Implementierungsmethode des Client-Endpunkts entspricht im Wesentlichen der Implementierung des Server-Endpunkts. Eine auf Anmerkungen basierende ist verfügbar. Verwenden Sie diese.

Ich habe es nicht ausprobiert, aber es scheint möglich zu sein, eine Klasse, die javax.websocket.Endpoint erbt, als Client-Endpunkt-Implementierung zu registrieren.

@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 ist eine selbst erstellte Komponente zum Anzeigen von Text
                        //Die Y-Koordinaten werden so verschoben, dass die Texte in einer Reihe stehen.
            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")
    }
}

Aufrufen des Client-Endpunkts

Eine Klasse namens ClientManager ist für den Aufruf des Clients vorbereitet. Verwenden Sie sie daher.

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

Dadurch wird eine Verbindung zum WebSocket-Server hergestellt. Wenn Sie eine Nachricht an den Server senden möchten:

session.asyncRemote.sendText(text)

demo

out.gif

Quellcode

https://github.com/yyYank/chatppoimono

Referenz-URL

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

Recommended Posts

Erstellen Sie eine Chat-App mit WebSocket (Tyrus) + libGDX + Kotlin
[Rails6] Erstelle eine neue App mit Rails [Anfänger]
Ich habe eine Janken App mit Kotlin gemacht
[Rails 5] Erstelle eine neue App mit Rails [Anfänger]
Erstellen Sie mit Spring Boot eine einfache Such-App
Erstellen Sie einen Team-Chat mit Rails Action Cable
Üben Sie das Erstellen einer einfachen Chat-App mit Docker + Sinatra
Ich habe eine Chat-App erstellt.
Erstellen Sie einen Spielplatz mit Xcode 12
[Rails] Ich habe versucht, eine Mini-App mit FullCalendar zu erstellen
Erstellen Sie eine Hello World-Webanwendung mit Spring Framework + Jetty
Erstellen Sie mit Docker eine Vue3-Umgebung!
Erstellen Sie eine Memo-App mit Tomcat + JSP + Servlet + MySQL mit Eclipse
Erstellen Sie eine App mit Spring Boot 2
Erstellen einer Timer-App mit Schlamm
Erstellen Sie eine neue App mit Rails
Erstellen Sie eine App mit Spring Boot
Erstellen Sie eine Befehlszeilen-App mit maven
Versuchen Sie, eine Server-Client-App zu erstellen
Erstellen Sie Ausnahmen mit einer Fluid-Schnittstelle
Erstellen Sie eine Restaurant-Such-App mit der IBM Watson + Guru Navi-API (mit Quelle).
[Kotlin / Android] Erstellen Sie eine benutzerdefinierte Ansicht
Erstellen Sie ein Maven-Projekt mit Befehlen
Erstellen Sie mit dem Befehl cURL + tar ein Spring Boot-App-Entwicklungsprojekt
Erstellen Sie mit Rails x LineBot eine App für die Zusammenfassung von technischen Nachrichten im LINEnews-Stil! [Teil 1]
Erstellen Sie mit dem Befehl eine JAR-Datei
Erstellen Sie mit Spring Batch eine einfache On-Demand-Charge
[Schienenentnahme] Erstellen Sie eine einfache Entnahmefunktion mit Schienen
Erstellen eines einfachen Balkendiagramms mit MPAndroidChart
Erstellen Sie eine TODO-App in Java 7 Create Header
Erstellen Sie eine temporäre Klasse mit new Object () {}
Ich habe eine Janken App mit Android gemacht
Erstellen Sie eine Website mit Spring Boot + Gradle (jdk1.8.x)
[Memo] Erstellen Sie mit Docker ganz einfach eine CentOS 8-Umgebung
Erstellen Sie eine CSR mit erweiterten Informationen in Java
[Rails] Rails neu, um eine Datenbank mit PostgreSQL zu erstellen
[Windows] [IntelliJ] [Java] [Tomcat] Erstellen Sie mit IntelliJ eine Umgebung für Tomcat 9
Lassen Sie uns mit Javas Timer einen zeitgesteuerten Prozess erstellen! !!
Erstellen Sie eine Kotlin-App mit dem OpenJDK Docker-Container
[Java] Erstellen Sie eine Sammlung mit nur einem Element
Ich habe versucht, eine LINE-Klon-App zu erstellen
Erstellen Sie ein SandBox-Konto mit Fastlane Spaces IP
Erstellen Sie eine Mehrschlüsselkarte mit einer Standardbibliothek
Erstellen Sie einen Web-API-Server mit Spring Boot
Erstellen Sie mit Docker eine Spring Boot-Entwicklungsumgebung