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:
WARNINGI 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:
WARNINGI 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.
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.