Einen WebSocket-Server in Java schreiben
Dieses Beispiel zeigt Ihnen, wie Sie einen WebSocket-API-Server mit Oracle Java erstellen.
Obwohl andere serverseitige Sprachen verwendet werden können, um einen WebSocket-Server zu erstellen, verwendet dieses Beispiel Oracle Java, um den Beispielcode zu vereinfachen.
Dieser Server entsprichtRFC 6455 und behandelt daher nur Verbindungen von Chrome ab Version 16, Firefox 11, IE 10 und höher.
Erste Schritte
WebSockets kommunizieren über eineTCP (Transmission Control Protocol)-Verbindung. DieServerSocket
-Klasse von Java befindet sich imjava.net
-Paket.
ServerSocket
DerServerSocket
-Konstruktor akzeptiert einen einzelnen Parameterport
vom Typint
.
Wenn Sie die ServerSocket-Klasse instanziieren, wird sie an die Portnummer gebunden, die Sie durch dasport-Argument angegeben haben.
Hier ist eine Implementierung, aufgeteilt in Teile:
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Base64;import java.util.Scanner;import java.util.regex.Matcher;import java.util.regex.Pattern;public class WebSocket { public static void main(String[] args) throws IOException, NoSuchAlgorithmException { ServerSocket server = new ServerSocket(80); try { System.out.println("Server has started on 127.0.0.1:80.\r\nWaiting for a connection…"); Socket client = server.accept(); System.out.println("A client connected.");
Socket-Methoden
java.net.Socket.getInputStream()
Gibt einen Eingabestrom für diesen Socket zurück.
java.net.Socket.getOutputStream()
Gibt einen Ausgabestrom für diesen Socket zurück.
OutputStream-Methoden
write(byte[] b, int off, int len)
Schreibtlen
Bytes aus dem angegebenen Bytearray, beginnend bei Offsetoff
, in diesen Ausgabestrom.
InputStream-Methoden
read(byte[] b, int off, int len)
Liest bis zulen Bytes Daten aus dem Eingabestrom in ein Bytearray.
Lassen Sie uns unser Beispiel erweitern.
InputStream in = client.getInputStream();OutputStream out = client.getOutputStream();Scanner s = new Scanner(in, "UTF-8");
Handshaking
Wenn ein Client eine Verbindung zu einem Server herstellt, sendet er eine GET-Anfrage, um die Verbindung von einer einfachen HTTP-Anfrage auf einen WebSocket aufzurüsten. Dies wird als Handshaking bezeichnet.
try { String data = s.useDelimiter("\\r\\n\\r\\n").next(); Matcher get = Pattern.compile("^GET").matcher(data);
Das Erstellen der Antwort ist einfacher, als zu verstehen, warum Sie es auf diese Weise tun müssen.
Sie müssen:
- Den Wert desSec-WebSocket-Key-Request-Headers ohne führende und nachfolgende Leerzeichen erhalten
- Ihn mit "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" verknüpfen
- SHA-1 und Base64 davon berechnen
- Ihn als Wert desSec-WebSocket-Accept-Response-Headers als Teil einer HTTP-Antwort zurückschreiben.
if (get.find()) { Matcher match = Pattern.compile("Sec-WebSocket-Key: (.*)").matcher(data); match.find(); byte[] response = ("HTTP/1.1 101 Switching Protocols\r\n" + "Connection: Upgrade\r\n" + "Upgrade: websocket\r\n" + "Sec-WebSocket-Accept: " + Base64.getEncoder().encodeToString(MessageDigest.getInstance("SHA-1").digest((match.group(1) + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes("UTF-8"))) + "\r\n\r\n").getBytes("UTF-8"); out.write(response, 0, response.length);
Nachrichten dekodieren
Nach einem erfolgreichen Handshake kann der Client Nachrichten an den Server senden, aber jetzt sind diese kodiert.
Wenn wir "abcdef" senden, erhalten wir diese Bytes:
129 134 167 225 225 210 198 131 130 182 194 135
129:
FIN (Ist dies die gesamte Nachricht?) RSV1 RSV2 RSV3 Opcode 1 0 0 0 0x1=0001 FIN: Sie können Ihre Nachricht in Frames senden, aber jetzt halten Sie es einfach.Opcode0x1 bedeutet, dass dies ein Text ist.Vollständige Liste der Opcodes
134:
Wenn das zweite Byte minus 128 zwischen 0 und 125 liegt, ist dies die Länge der Nachricht. Wenn es 126 ist, sind die folgenden 2 Bytes (16-Bit-Unsigned-Integer), wenn 127, die folgenden 8 Bytes (64-Bit-Unsigned-Integer, das höchstwertige Bit MUSS 0 sein) die Länge.
Hinweis:Es kann 128 annehmen, da das erste Bit immer 1 ist.
167, 225, 225 und 210 sind die Bytes des Schlüssels zum Dekodieren. Sie ändern sich jedes Mal.
Die verbleibenden kodierten Bytes sind die Nachricht.
Dekodierungsalgorithmus
Dekodiertes Byte = Kodiertes Byte XOR (Position des kodierten Bytes BITWEISE UND 0x3)tes Byte des Schlüssels
Beispiel in Java:
byte[] decoded = new byte[6]; byte[] encoded = new byte[] { (byte) 198, (byte) 131, (byte) 130, (byte) 182, (byte) 194, (byte) 135 }; byte[] key = new byte[] { (byte) 167, (byte) 225, (byte) 225, (byte) 210 }; for (int i = 0; i < encoded.length; i++) { decoded[i] = (byte) (encoded[i] ^ key[i & 0x3]); } } } finally { s.close(); } } finally { server.close(); } }}
Verwandt
MDN-Feedback-Box
Diese Seite wurde automatisch aus dem Englischen übersetzt.