Ich habe mit WebSocket eine sehr einfache Chat-App erstellt.
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
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.
Die Verwendung von Tyrus ist sehr einfach.
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.
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.
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.
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")
}
}
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
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