Friday, December 4, 2015

Websocket Server and Client in Java


In this post we are going to develop a simple Websocket Server and Client in Java. Before writing code for server and client, we first need to add the following dependencies in pom.xml, if it's Maven project, otherwise you can download these jars manually and add it to your project dependency.


 <dependencies>
  <dependency>
    <groupId>org.glassfish.tyrus</groupId>
    <artifactId>tyrus-server</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.tyrus</groupId>
    <artifactId>tyrus-client</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.tyrus</groupId>
    <artifactId>tyrus-container-grizzly</artifactId>
    <version>1.1</version>
</dependency>
</dependencies>


The above dependencies have a tyrus-server, tyrus-client and a tyrus-container for the server to run.


Now we will be creating the server end point class called TestServerEndPoint -

import java.io.IOException;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.*;

@ServerEndpoint(value="/testServerEndPoint")
public class TestServerEndpoint {
   
    @OnOpen
    public void onOpen(Session session) {
    System.out.println("Session opened with session Id "+session.getId());
    }
   
    @OnMessage
    public void onMessage(String message, Session session) {
    System.out.println("Received message: "+message+" from session Id "+session.getId());
    try {
    session.getBasicRemote().sendText(message);
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
   
    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
    System.out.println("Closed session "+session.getId());
    }
   
   

}



This is the server end point of we socket. The @ServerEndpoint denotes that this class is going to act as the server end point. The value in the ServerEndpoint annotation will be used in the URL while connecting to the server. We have over ridden three methods in this class -
1) The onOpen method will be called whenever a client establishes a session with the server. Each session will be assigned an Id. We are printing out that Id, whenever a client connects to our server.
2) The onMessage method will be called whenever a client sends in a message to the server. We are printing that message along with the ID of the session sending that message. The server is then sending back the same message to the client.
3) The onClose method will be called whenever a client closes the session. We are printing out the session ID of the session being closed.

We will be creating a runnable class for the server called Test Server -

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.websocket.DeploymentException;

import org.glassfish.tyrus.server.Server;

public class TestServer {
   
    public static void main(String[] args) {
    Server testServer = new Server("localhost", 8025, "/testServer", TestServerEndpoint.class);
    try {
    testServer.start();
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    System.out.print("Please press a key to stop the server.");
    reader.readLine();
    testServer.stop();
    } catch (DeploymentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
   
    }

}


In the main method we are creating an instance of Server class. The TestServer will be running on port 8025 with TestServerEndpoint as it's server end point. The "/testServer" will be used in the URL when the client will be connecting to the server. We then call testServer.start() to start the server. When you run the above class, the server should start successfully -


Dec 04, 2015 11:22:23 PM org.glassfish.tyrus.server.ServerContainerFactory create
INFO: Provider class loaded: org.glassfish.tyrus.container.grizzly.GrizzlyEngine
Dec 04, 2015 11:22:24 PM org.glassfish.grizzly.http.server.NetworkListener start
INFO: Started listener bound to [0.0.0.0:8025]
Dec 04, 2015 11:22:24 PM org.glassfish.grizzly.http.server.HttpServer start
INFO: [HttpServer] Started.
Dec 04, 2015 11:22:24 PM org.glassfish.tyrus.server.Server start
INFO: WebSocket Registered apps: URLs all start with ws://localhost:8025
Dec 04, 2015 11:22:24 PM org.glassfish.tyrus.server.Server start
INFO: WebSocket server started.
Please press a key to stop the server.



Now we will be creating a client which will be connecting to our server. First we will be creating an end point for the client similar to the end point of the server -


import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;

@ClientEndpoint
public class TestClientEndpoint {
   
    @OnOpen
    public void onOpen(Session session) {
      
    }
   
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("Received message from server "+message);
    }
   
    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
      
    }
   
   

}


We have created an end point for client called TestClientEndpoint. The methods over ridden are the same as the methods over ridden in the TestServerEndpoint. In the onMessage method, we are printing out the message received from the server.

Now we will be creating the client.

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import javax.websocket.DeploymentException;
import javax.websocket.Session;

import org.glassfish.tyrus.client.ClientManager;

public class TestClient {
   
    public static void main(String[] args) {
        ClientManager client = ClientManager.createClient();
        try {
            Session clientSession = client.connectToServer(TestClientEndpoint.class, new URI("ws://localhost:8025/testServer/testServerEndPoint"));
            clientSession.getBasicRemote().sendText("Hello! How are you?");
            Thread.sleep(5000);
            clientSession.close();
        } catch (DeploymentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (URISyntaxException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
 

We have created an instance of client. In the URL we are using
"ws://localhost:8025/testServer/testServerEndPoint"
ws denotes a websocket connection between the client and the server.
localhost:8025 denotes we are connecting to the server locally at port 8025.
/testServer is the server instance as mentioned in our TestServer class.
/testServerEndpoint is the server end point as mentioned in our TestServerEndpoint class.

In the main method we are creating an instance of client and then we are using the client instance to connect to the server. On connecting to the server, a session is getting generated and then we are using the session to send a message to the server. We are finally closing the session. The Thread.sleep(5000) is introduced in order to give some time to the client to receive the message from the server.

Console output of Server -
Dec 05, 2015 12:04:46 AM org.glassfish.tyrus.server.ServerContainerFactory create
INFO: Provider class loaded: org.glassfish.tyrus.container.grizzly.GrizzlyEngine
Dec 05, 2015 12:04:47 AM org.glassfish.grizzly.http.server.NetworkListener start
INFO: Started listener bound to [0.0.0.0:8025]
Dec 05, 2015 12:04:47 AM org.glassfish.grizzly.http.server.HttpServer start
INFO: [HttpServer] Started.
Dec 05, 2015 12:04:47 AM org.glassfish.tyrus.server.Server start
INFO: WebSocket Registered apps: URLs all start with ws://localhost:8025
Dec 05, 2015 12:04:47 AM org.glassfish.tyrus.server.Server start
INFO: WebSocket server started.
Please press a key to stop the server.Session opened with session Id e993682e-d5ca-428c-8267-88022abfea1d
Received message: Hello! How are you? from session Id e993682e-d5ca-428c-8267-88022abfea1d
Closed session e993682e-d5ca-428c-8267-88022abfea1d


 We can see from the console of the server that a session was created by the client. And then it received a message from the client "Hello! How are you?" and finally the session was closed.

Console output of Client-
Received message from server Hello! How are you?

In the console output of the client, we can see the message received from the server.

Congrats!!! You have successfully created a websocket server and a client. If you face any issues, please mention your issue in the comments below, and I will try to reply to it as soon as I can. Till then, enjoy coding. :-P

No comments:

Post a Comment