MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

Implementando um servidor de WebSocket em Java

Esta tradução está incompleta. Por favor, ajude a traduzir este artigo.

Introdução

Este exemplo mostra como criar um servidor de WebSocket API usando Oracle Java.

Apesar de poder usar outras linguagens server-side para criar um servidor de WebSocket, este usa Oracle Java para simplificar o código de exemplo.

Este servidor está de acordo com a RFC 6455, no entanto ele só lida com conexões do Chrome versão 16, Firefox 11, IE 10 ou superior.

Primeiros passos

Os WebSockets comunicam por uma conexão TCP (Transmission Control Protocol). A classe ServerSocket do Java se encontra no pacote java.net.

ServerSocket

Construtor:

ServerSocket(int porta)

When you instantiate the ServerSocket class, it is bound to the port number you specified by theport argument.

Here's how to implement what we have learnt:

import java.net.ServerSocket;
import java.net.Socket;

public class Server{
    public static void main(String[] args){
        ServerSocket server = new ServerSocket(80);

        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

Métodos:

OutputStream

Métodos:

write(byte[] b, int off, int len)

Escreve a quantidade (len) de bytes do array informado, iniciando na possição (off) deste output stream.

InputStream

Métodos:

read(byte[] b, int off, int len)

Reads up to len bytes of data from the input stream into an array of bytes.

Let us extend our example.

Socket client = server.accept();

System.out.println("A client connected.");

InputStream in = client.getInputStream();

OutputStream out = client.getOutputStream();

new Scanner(in, "UTF-8").useDelimiter("\\r\\n\\r\\n").next();

Handshaking

When a client connects to a server, it sends a GET request to upgrade the connection to a WebSocket from a simple HTTP request. This is known as handshaking.

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

//translate bytes of request to string
String data = new Scanner(in,"UTF-8").useDelimiter("\\r\\n\\r\\n").next();

Matcher get = Pattern.compile("^GET").matcher(data);

if (get.find()) {
    
} else {

}

Creating the response is easier than understanding why you must do it in this way.

You must,

  1. Obtain the value of Sec-WebSocket-Key request header without any leading and trailing whitespace
  2. Link it with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
  3. Compute SHA-1 and Base64 code of it
  4. Write it back as value of Sec-WebSocket-Accept response header as part of a HTTP response.
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: "
            + DatatypeConverter
            .printBase64Binary(
                    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);
}

Decodificando mensagens

After a successful handshake, client can send messages to the server, but now these are encoded.

If we send "abcdef", we get these bytes:

129 134 167 225 225 210 198 131 130 182 194 135

- 129:

FIN (Is this the whole message?) RSV1 RSV2 RSV3 Opcode
1 0 0 0 0x1=0001

FIN: You can send your message in frames, but now keep things simple.
Opcode 0x1 means this is a text. Full list of Opcodes

- 134:

If the second byte minus 128 is between 0 and 125, this is the length of the message. If it is 126, the following 2 bytes (16-bit unsigned integer), if 127, the following 8 bytes (64-bit unsigned integer, the most significant bit MUST be 0) are the length.

I can take 128 because the first bit is always 1.

- 167, 225, 225 and 210 are the bytes of the key to decode. It changes every time.

- The remaining encoded bytes are the message.

Decoding algorithm

decoded byte = encoded byte XOR (position of encoded byte BITWISE AND 0x3)th byte of key

Example in Java:

byte[] decoded = new byte[6];
byte[] encoded = new byte[] {198, 131, 130, 182, 194, 135};
byte[] key = byte[4] {167, 225, 225, 210};

for (int i = 0; i < encoded.length; i++) {
    decoded[i] = (byte)(encoded[i] ^ key[i & 0x3]);
}
 

Etiquetas do documento e colaboradores

 Colaboradores desta página: carlosroberto555
 Última atualização por: carlosroberto555,