My Blog
989 words
5 minutes
Java Websockets

Introduction#

Websockets are a great way to communicate between a client and a server. They are a great way to send and receive messages in real-time. In this post, I will be discussing how to use websockets in Java, and what I personally think about them. For this tutorial I will be making a simple chat application using websockets.

Getting Started#

To get started with websockets in Java, you have a few options. You can use the javax.websocket package, or you can use a library like tyrus. I personally prefer the library org.java-websocket because it is easier to use and has better documentation.

How to Use#

For this example, I will be using org.java-websocket. First, you need to add the dependency to your pom.xml file:

<dependency>
  <groupId>org.java-websocket</groupId>
  <artifactId>Java-WebSocket</artifactId>
  <version>1.5.6</version>
</dependency>

If you are using Gradle, you can add the dependency to your build.gradle.kts file:

implementation("org.java-websocket:Java-WebSocket:1.5.6")

Server Example#

Once you have added the dependency, you can start using websockets in your Java application. Here is an example of how to create a simple chat websocket server hosted on port 8912:

WARNING

I am using Java 17 and Java-WebSocket 1.5.6 for this example.
Using a different version of Java or Java-WebSocket may require changes to the code.

package dev.hyperskys.chatserver;

import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;

public class ChatServerApplication extends WebSocketServer {

    private final HashMap<WebSocket, ClientHandshake> connections = new HashMap<>();
    private final ArrayList<String> usernames = new ArrayList<>();

    public ChatServerApplication() {
        super(new InetSocketAddress(8912));
    }

    @Override
    public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
        String username = clientHandshake.getFieldValue("Username");
        if (username == null) {
            System.out.println("Connection attempt from " + webSocket.getRemoteSocketAddress() + " has been rejected due to missing username!");
            webSocket.send("You must provide a username to connect to this server.");
            webSocket.close();
            return;
        }

        if (usernames.contains(username)) {
            System.out.println("Connection attempt from " + webSocket.getRemoteSocketAddress() + " has been rejected due to duplicate username!");
            webSocket.send("The username you provided is already in use.");
            webSocket.close();
            return;
        }

        System.out.println("Connection has been established with " + webSocket.getRemoteSocketAddress() + " using the username " + username + ".");
        broadcast(username + " has connected to the server.");
        connections.put(webSocket, clientHandshake);
        usernames.add(username);
    }

    @Override
    public void onClose(WebSocket webSocket, int code, String reason, boolean remote) {
        String username = connections.get(webSocket).getFieldValue("Username");
        System.out.println("Connection has been closed with " + webSocket.getRemoteSocketAddress() + ".");
        broadcast(username + " has disconnected from the server.");
        connections.remove(webSocket);
        usernames.remove(username);
    }

    @Override
    public void onMessage(WebSocket webSocket, String message) {
        String username = connections.get(webSocket).getFieldValue("Username");
        System.out.println("Received message: " + message);
        broadcast(username + ": " + message);
    }

    @Override
    public void onError(WebSocket webSocket, Exception exception) {
        System.out.println("An error occurred while handling a WebSocket connection.");
        exception.printStackTrace();
    }

    @Override
    public void onStart() {
        System.out.println("Chat Server has started on port " + getPort() + ".");
    }

    public static void main(String[] args) {
        new ChatServerApplication().start();
    }

}

Client Example#

Continuing on here is an example of how to create a simple chat websocket client:

WARNING

I am using Java 8 and Java-WebSocket 1.5.6 for this example.
Using a different version of Java or Java-WebSocket may require changes to the code.

package dev.hyperskys.chatclient;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;

public class ChatClientApplication {
    
    public static void main(String[] args) {
        try {
            WebSocketClient webSocketClient = getWebSocketClient("HyperSkys");
            webSocketClient.connect();
            
            Scanner scanner = new Scanner(System.in);
            while (!webSocketClient.isClosed()) {
                String message = scanner.nextLine();
                webSocketClient.send(message);
            }
        } catch (URISyntaxException exception) {
            throw new RuntimeException(exception);
        }
    }

    private static WebSocketClient getWebSocketClient(String username) throws URISyntaxException {
        HashMap<String, String> headers = new HashMap<>();
        headers.put("Username", username);
        return new WebSocketClient(new URI("ws://" + "localhost" + ":" + 8912), headers) {
            @Override
            public void onOpen(ServerHandshake serverHandshake) {
                System.out.println("Connection has been established with the server.");
            }

            @Override
            public void onMessage(String message) {
                System.out.println("[CHAT] " + username + ": " + message);
            }

            @Override
            public void onClose(int code, String reason, boolean remote) {
                System.out.println("The server has closed the connection.");
            }

            @Override
            public void onError(Exception exception) {
                System.out.println("An error occurred while handling a WebSocket connection.");
                exception.printStackTrace();
            }
        };
    }

}

Server Explanation#

In the server example, we create a new ChatServerApplication class that extends WebSocketServer. We override the onOpen, onClose, onMessage, onError, and onStart methods to handle the different events that can occur during the lifecycle of a websocket connection. In the onOpen method, we check if the client has provided a username, and if not, we reject the connection. We also check if the username is already in use, and if so, we reject the connection. If everything is okay, we add the connection to the connections map and the username to the usernames list. In the onClose method, we remove the connection from the connections map and the username from the usernames list. In the onMessage method, we broadcast the message to all connected clients. In the onError method, we log the error. In the onStart method, we log that the server has started.

Client Explanation#

In the client example, we create a new ChatClientApplication class that connects to the server using the provided username. We create a new WebSocketClient and connect to the server. We then enter a loop that reads messages from the console and sends them to the server. In the onOpen method, we log that the connection has been established. In the onMessage method, we log the received message. In the onClose method, we log that the server has closed the connection. In the onError method, we log the error.

For More Information#

For more information on websockets in Java, you can check out the Java-WebSocket library on GitHub. It has a lot of great examples and documentation that can help you get started with websockets in Java. You can also check out the javax.websocket package in the Java EE API documentation. It has a lot of great information on how to use websockets in Java there as well.

TooTallNate
/
Java-WebSocket
Waiting for api.github.com...
00K
0K
0K
Waiting...

Conclusion#

Websockets are a great way to communicate between a client and a server. They are a great way to send and receive messages in real-time. I hope this post has helped you understand how to use websockets in Java, and how to create a simple chat application using them. If you have any questions or comments, feel free to contact me.

Java Websockets
https://hyperskys.dev/posts/java-websockets/
Author
HyperSkys
Published at
2024-04-30