Standalone WebSocket server without JEE/application server

Tried using Stefan's code. And currently it doesn't work well (I'm using Firefox). Websocket packets larger than 1024 bytes are being splitted into TCP segments, so reassembling is required. Here is an updated code for reading browser packet:

private static void processResponse(InputStream inputStream, OutputStream outputStream) throws IOException {
    int readPacketLength = 0;
    byte[] packet = new byte[1024];
    ByteArrayOutputStream packetStream = new ByteArrayOutputStream();

    while(true) {
        readPacketLength = inputStream.read(packet);

        if(readPacketLength != -1) {
            if ((packet[0] & (byte) 15) == (byte) 8) { // Disconnect packet
                outputStream.write(packet, 0, readPacketLength);
                // returning the same packet for client to terminate connection
                outputStream.flush();
                return;
            }
            byte messageLengthByte = 0;
            int messageLength = 0;
            int maskIndex = 2;
            int messageStart = 0;
            //b[0] is always text in my case so no need to check;
            byte data = packet[1];
            byte op = (byte) 127; // 0111 111
            messageLengthByte = (byte) (data & op);

            int totalPacketLength = 0;
            if (messageLengthByte == (byte) 126 || messageLengthByte == (byte) 127) {
                if (messageLengthByte == (byte) 126) {
                    maskIndex = 4;
                    // if (messageLengthInt==(byte)126), then 16-bit length is stored in packet[2] and [3]
                    ByteBuffer messageLength16Bit = ByteBuffer.allocateDirect(4);
                    messageLength16Bit.order(ByteOrder.BIG_ENDIAN);
                    messageLength16Bit.put((byte) 0x00);
                    messageLength16Bit.put((byte) 0x00);
                    messageLength16Bit.put(packet, 2, 2);
                    messageLength16Bit.flip();
                    messageLength = messageLength16Bit.getInt();
                    totalPacketLength = messageLength + 8;
                } else {
                    maskIndex = 10;
                    // if (messageLengthInt==(byte)127), then 64-bit length is stored in bytes [2] to [9]. Using only 32-bit
                    ByteBuffer messageLength64Bit = ByteBuffer.allocateDirect(4);
                    messageLength64Bit.order(ByteOrder.BIG_ENDIAN);
                    messageLength64Bit.put(packet, 6, 4);
                    messageLength64Bit.flip();
                    messageLength = messageLength64Bit.getInt();
                    totalPacketLength = messageLength + 14;
                }

                if (readPacketLength != totalPacketLength) {
                    packetStream.write(packet, 0, readPacketLength);

                    int lastPacketLength = 0;
                    while (readPacketLength < totalPacketLength) {
                        packet = new byte[1024];
                        readPacketLength += lastPacketLength = inputStream.read(packet);
                        packetStream.write(packet, 0, lastPacketLength);
                    }
                    packet = packetStream.toByteArray();
                    packetStream.reset();
                }
            }
            else { // using message length from packet[1]
                messageLength = messageLengthByte;
            }

            byte[] masks = new byte[4];
            int i=0; int j=0;
            for(i = maskIndex; i < (maskIndex+4); i++) {
                masks[j] = packet[i];
                j++;
            }

            messageStart = maskIndex + 4;

            byte[] message = new byte[messageLength];
            for(i = messageStart, j = 0; i < readPacketLength; i++, j++){
                message[j] = (byte) (packet[i] ^ masks[j % 4]);
            }
            System.out.println("Received message: " + new String(message));
            packet = new byte[1024];
        }
    }
}

Java 11 Server Code:

package org.treez.server.websocket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.DatatypeConverter;;

public class WebSocketServer{


    public static void main(String[] args){

        int portNumber = 8000;

        ServerSocket server;
        try {
            server = new ServerSocket(portNumber);
        } catch (IOException exception) {
            throw new IllegalStateException("Could not create web server", exception);
        }


        Socket clientSocket;
        try {
            clientSocket = server.accept(); //waits until a client connects
        } catch (IOException waitException) {
            throw new IllegalStateException("Could not wait for client connection", waitException);
        }

        InputStream inputStream;
        try {
            inputStream  = clientSocket.getInputStream();
        } catch (IOException inputStreamException) {
            throw new IllegalStateException("Could not connect to client input stream", inputStreamException);
        }

        OutputStream outputStream;
        try {
            outputStream  = clientSocket.getOutputStream();
        } catch (IOException inputStreamException) {
            throw new IllegalStateException("Could not connect to client input stream", inputStreamException);
        }

        try {
            doHandShakeToInitializeWebSocketConnection(inputStream, outputStream);
        } catch (UnsupportedEncodingException handShakeException) {
            throw new IllegalStateException("Could not connect to client input stream", handShakeException);
        }


        try {        
            outputStream.write(encode("Hello from Server!"));
            outputStream.flush();
        } catch (UnsupportedEncodingException e) {          
            e.printStackTrace();
        } catch (IOException e) {       
            e.printStackTrace();
        }   

         try {
                printInputStream(inputStream);
            } catch (IOException printException) {
                throw new IllegalStateException("Could not connect to client input stream", printException);
            }

    }

    //Source for encoding and decoding:
    //https://stackoverflow.com/questions/8125507/how-can-i-send-and-receive-websocket-messages-on-the-server-side


    private static void printInputStream(InputStream inputStream) throws IOException {
        int len = 0;            
        byte[] b = new byte[1024];
        //rawIn is a Socket.getInputStream();
        while(true){
            len = inputStream.read(b);
            if(len!=-1){

                byte rLength = 0;
                int rMaskIndex = 2;
                int rDataStart = 0;
                //b[0] is always text in my case so no need to check;
                byte data = b[1];
                byte op = (byte) 127;
                rLength = (byte) (data & op);

                if(rLength==(byte)126) rMaskIndex=4;
                if(rLength==(byte)127) rMaskIndex=10;

                byte[] masks = new byte[4];

                int j=0;
                int i=0;
                for(i=rMaskIndex;i<(rMaskIndex+4);i++){
                    masks[j] = b[i];
                    j++;
                }

                rDataStart = rMaskIndex + 4;

                int messLen = len - rDataStart;

                byte[] message = new byte[messLen];

                for(i=rDataStart, j=0; i<len; i++, j++){
                    message[j] = (byte) (b[i] ^ masks[j % 4]);
                }

                System.out.println(new String(message)); 

                b = new byte[1024];

            }
        }
    }


    public static byte[] encode(String mess) throws IOException{
        byte[] rawData = mess.getBytes();

        int frameCount  = 0;
        byte[] frame = new byte[10];

        frame[0] = (byte) 129;

        if(rawData.length <= 125){
            frame[1] = (byte) rawData.length;
            frameCount = 2;
        }else if(rawData.length >= 126 && rawData.length <= 65535){
            frame[1] = (byte) 126;
            int len = rawData.length;
            frame[2] = (byte)((len >> 8 ) & (byte)255);
            frame[3] = (byte)(len & (byte)255); 
            frameCount = 4;
        }else{
            frame[1] = (byte) 127;
            int len = rawData.length;
            frame[2] = (byte)((len >> 56 ) & (byte)255);
            frame[3] = (byte)((len >> 48 ) & (byte)255);
            frame[4] = (byte)((len >> 40 ) & (byte)255);
            frame[5] = (byte)((len >> 32 ) & (byte)255);
            frame[6] = (byte)((len >> 24 ) & (byte)255);
            frame[7] = (byte)((len >> 16 ) & (byte)255);
            frame[8] = (byte)((len >> 8 ) & (byte)255);
            frame[9] = (byte)(len & (byte)255);
            frameCount = 10;
        }

        int bLength = frameCount + rawData.length;

        byte[] reply = new byte[bLength];

        int bLim = 0;
        for(int i=0; i<frameCount;i++){
            reply[bLim] = frame[i];
            bLim++;
        }
        for(int i=0; i<rawData.length;i++){
            reply[bLim] = rawData[i];
            bLim++;
        }

        return reply;
    }

    private static void doHandShakeToInitializeWebSocketConnection(InputStream inputStream, OutputStream outputStream) throws UnsupportedEncodingException {
        String data = new Scanner(inputStream,"UTF-8").useDelimiter("\\r\\n\\r\\n").next();

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

        if (get.find()) {
            Matcher match = Pattern.compile("Sec-WebSocket-Key: (.*)").matcher(data);
            match.find();                 

            byte[] response = null;
            try {
                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");
            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            try {
                outputStream.write(response, 0, response.length);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else {

        }
    }
}

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>TreezHttpServer</groupId>
  <artifactId>TreezHttpServer</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <resources>
      <resource>
        <directory>src</directory>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <configuration>
          <release>11</release>
        </configuration>
      </plugin>
    </plugins>    

  </build>

  <dependencies>

    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.2.11</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        <artifactId>jaxb-core</artifactId>
        <version>2.2.11</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        <artifactId>jaxb-impl</artifactId>
        <version>2.2.11</version>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>activation</artifactId>
        <version>1.1.1</version>
    </dependency>

  </dependencies>
</project>

JavaScript Client:

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>WebSocket Client</title>

 <script type="text/javascript">

      var wsocket;      

      function connect() {         

          wsocket = new WebSocket("ws://localhost:8000");          
          wsocket.onopen = onopen;
          wsocket.onmessage = onmessage;
          wsocket.onclose = onclose; 
      }

      function onopen() {
          console.log("Connected!");             
          wsocket.send('hello from client');
      }

      function onmessage(event) { 
         console.log("Data received: " + event.data); 
      }

      function onclose(e) {
         console.log("Connection closed.");              
      }

      window.addEventListener("load", connect, false);

  </script>

</head>

<body>
</body>

</html>

https://github.com/TooTallNate/Java-WebSocket is a full WebSockets server and client implementation in Java SE, no enterprise/web app server needed.