J'ai créé une application de chat très simple en utilisant WebSocket.
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
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.
Utiliser Tyrus est très simple.
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.
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.
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.
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")
}
}
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
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