Clarification on websocket - java

I am exploring Websocket now. I need some clarifications. I am using websocket with tomcat. 
How tomcat map websocket requests to specific java class. for an example, we can give servlet class in web.xml. But How it works for websocket?

1- Javascript :
Declare variables for the websocket as the following :
var websocket;
var address = "ws://localhost:8080/appName/MyServ";
notice that appName is your application name and MyServ is the Endpoint
also in your script add a function to open the connection :
var websocket;
var address = "ws://localhost:8080/appName/MyServ";
function openWS() {
websocket = new WebSocket(address);
websocket.onopen = function(evt) {
onOpen(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
websocket.onclose = function(evt) {
onClose(evt)
};
}
function onOpen(evt) {
// what will happen after opening the websocket
}
function onClose(evt) {
alert("closed")
}
function onMessage(evt) {
// what do you want to do when the client receive the message?
alert(evt.data);
}
function onError(evt) {
alert("err!")
}
function SendIt(message) {
// call this function to send a msg
websocket.send(message);
}
2- At the server side, you need a ServerEndpoint : I call it myServ in the script above.
NOW, I think this is exactly what you need:
Declare any Java POJO class WebSocket server endpoint by annotating it with #ServerEndpoint
import java.io.IOException
import javax.servlet.ServletContext;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
#ServerEndpoint(value="/MyServ")
public class MyServ{
#OnMessage
public void onMessage(Session session, String msg) throws IOException {
// todo when client send msg
// tell the client that you received the message!
try {
session.getBasicRemote().sendText("I got your message :"+ msg);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#OnOpen
public void onOpen (Session session) {
// tell the client the connection is open!
try {
session.getBasicRemote().sendText("it is open!");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#OnClose
public void onClose (Session session) {
System.out.println("websocket closed");
}
#OnError
public void onError (Session session){
}
}

Related

Tomcat websocket closes connection

I run simple websocket server on Tomcat:
package server.ws;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.server.ServerEndpoint;
#ServerEndpoint("/websocketendpoint")
public class WsServer {
#OnOpen
public void onOpen(){
System.out.println("Open Connection ...");
}
#OnClose
public void onClose(){
System.out.println("Close Connection ...");
}
#OnMessage
public String onMessage(String message){
System.out.println("Message from the client: " + message);
String echoMsg = "Echo from the server : " + message;
return echoMsg;
}
#OnError
public void onError(Throwable e){
e.printStackTrace();
}
}
Client that connects to my server complains regarding Tomcat closes session after echo was transmitted. How to make the server to not close the connection after echo?
i'm not sure, but i guess onMessagehas no return value.
for me, the following code works fine and i have any problems
#OnMessage
public void message(final String message, final javax.websocket.Session session) throws IOException {
for (final Session s : session.getOpenSessions()) {
final Basic endpoint = s.getBasicRemote();
endpoint.sendText(message);
}
}

websocket client not returning connection

I have websocket server and now i need client to test its usage. I am using this clients code:
import org.msgpack.MessagePack;
import org.springframework.web.socket.BinaryMessage;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class TestApp {
public static void main(String[] args) {
try {
// open websocket
final WebsocketClientEndpoint clientEndPoint = new WebsocketClientEndpoint(new URI("ws://localhost:8080/websocket"));
// add listener
clientEndPoint.addMessageHandler(new WebsocketClientEndpoint.MessageHandler() {
public void handleMessage(String message) {
System.out.println(message);
}
});
// send message to websocket
clientEndPoint.sendMessage(new BinaryMessage(...));
// wait 5 seconds for messages from websocket
Thread.sleep(5000);
} catch (InterruptedException ex) {
System.err.println("InterruptedException exception: " + ex.getMessage());
} catch (URISyntaxException ex) {
System.err.println("URISyntaxException exception: " + ex.getMessage());
} catch (IOException e) {
e.printStackTrace();
}
}
}
import org.springframework.web.socket.BinaryMessage;
import java.net.URI;
import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
#ClientEndpoint
class WebsocketClientEndpoint {
Session userSession = null;
private MessageHandler messageHandler;
public WebsocketClientEndpoint(URI endpointURI) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, endpointURI);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Callback hook for Connection open events.
*
* #param userSession the userSession which is opened.
*/
#OnOpen
public void onOpen(Session userSession) {
System.out.println("opening websocket");
this.userSession = userSession;
}
/**
* Callback hook for Connection close events.
*
* #param userSession the userSession which is getting closed.
* #param reason the reason for connection close
*/
#OnClose
public void onClose(Session userSession, CloseReason reason) {
System.out.println("closing websocket");
this.userSession = null;
}
/**
* Callback hook for Message Events. This method will be invoked when a client send a message.
*
* #param message The text message
*/
#OnMessage
public void onMessage(String message) {
if (this.messageHandler != null) {
this.messageHandler.handleMessage(message);
}
}
/**
* register message handler
*
* #param msgHandler
*/
public void addMessageHandler(MessageHandler msgHandler) {
this.messageHandler = msgHandler;
}
/**
* Send a message.
*
* #param message
*/
public void sendMessage(BinaryMessage message) {
this.userSession.getAsyncRemote().sendObject(message);
}
/**
* Message handler.
*
* #author Jiji_Sasidharan
*/
public static interface MessageHandler {
public void handleMessage(String message);
}
}
When i run this client, my sever accepts it, i am using spring and
void afterConnectionEstablished(WebSocketSession session)
method of BinaryWebSocketHandler fires up and everything seems fine, however after this method, the client does not set userSession , it is still null so it always throw nullpointer exception on
this.userSession.getAsyncRemote().sendObject(message);
which is weird cuz server accepts connection. What is causing this problem? Is there a fix for it?
Thanks for help!
package websocket.client;
import java.net.URI;
import javax.websocket.*;
#ClientEndpoint
public class WSClient {
private static Object waitLock = new Object();
#OnMessage
public void onMessage(String message) {
//the new USD rate arrives from the websocket server side.
System.out.println("Received msg: " + message);
}
private static void wait4TerminateSignal() {
synchronized(waitLock) {
try {
waitLock.wait();
} catch (InterruptedException e) {}
}
}
public static void main(String[] args) {
WebSocketContainer container = null; //
Session session = null;
try {
//Tyrus is plugged via ServiceLoader API. See notes above
container = ContainerProvider.getWebSocketContainer();
//WS1 is the context-root of my web.app
//ratesrv is the path given in the ServerEndPoint annotation on server implementation
session = container.connectToServer(WSClient.class, URI.create("ws://localhost:8080/WS1/ratesrv"));
wait4TerminateSignal();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null) {
try {
session.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

Multiple messages on a Grizzly Websocket Connection

We are using Websockets from the Grizzly project and had expected that the implementation would allow multiple incoming messages over a connection to be processed at the same time. It appears that this is not the case or there is a configuration step that we have missed. To validate this I have created a modified echo test that delays in the onMessage after echoing the text. When a client sends multiple messages over the same connection the server always blocks until onMessage completes before processing a subsequent message. Is this the expected functionality?
The simplified server code is as follows:
package com.grorange.samples.echo;
import java.util.concurrent.atomic.AtomicBoolean;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.websockets.DataFrame;
import org.glassfish.grizzly.websockets.WebSocket;
import org.glassfish.grizzly.websockets.WebSocketAddOn;
import org.glassfish.grizzly.websockets.WebSocketApplication;
import org.glassfish.grizzly.websockets.WebSocketEngine;
public class Echo extends WebSocketApplication {
private final AtomicBoolean inMessage = new AtomicBoolean(false);
#Override
public void onClose(WebSocket socket, DataFrame frame) {
super.onClose(socket, frame);
System.out.println("Disconnected!");
}
#Override
public void onConnect(WebSocket socket) {
System.out.println("Connected!");
}
#Override
public void onMessage(WebSocket socket, String text) {
System.out.println("Server: " + text);
socket.send(text);
if (this.inMessage.compareAndSet(false, true)) {
try {
Thread.sleep(10000);
} catch (Exception e) {}
this.inMessage.set(false);
}
}
#Override
public void onMessage(WebSocket socket, byte[] bytes) {
socket.send(bytes);
if (this.inMessage.compareAndSet(false, true)) {
try {
Thread.sleep(Long.MAX_VALUE);
} catch (Exception e) {}
this.inMessage.set(false);
}
}
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.createSimpleServer("http://0.0.0.0", 8083);
WebSocketAddOn addOn = new WebSocketAddOn();
addOn.setTimeoutInSeconds(60);
for (NetworkListener listener : server.getListeners()) {
listener.registerAddOn(addOn);
}
WebSocketEngine.getEngine().register("", "/Echo", new Echo());
server.start();
Thread.sleep(Long.MAX_VALUE);
}
}
The simplified client code is:
Yes, it's expected.
The way to go is to pass message processing, inside onMessage, to a different thread.

Web Socket in Tomcat 7

I am new in web socket. I had learned some tutorial to implement web socket. But it is not working properly. I don't know what I have done wrongly.
note: I have not done any configuration (web.xml) and I have been used tomcat 7.0.47,jdk 1.6.0_24
This is My Server side code:
package com.hmkcode;
import java.io.IOException;
import java.util.LinkedList;
import javax.websocket.EncodeException;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
#ServerEndpoint(value="/websocket/{client-id}")
public class MyServerEndpoint {
private static final LinkedList<Session> clients = new LinkedList<Session>();
#OnOpen
public void onOpen(Session session) {
clients.add(session);
}
#OnMessage
public void onMessage(String message,#PathParam("client-id") String clientId) {
for (Session client : clients) {
try {
client.getBasicRemote().sendObject(clientId+": "+message);
} catch (IOException e) {
e.printStackTrace();
} catch (EncodeException e) {
e.printStackTrace();
}
}
}
#OnClose
public void onClose(Session peer) {
clients.remove(peer);
}
}
This is my Web client code
var URL = "ws://localhost:8080/WebSocket1/websocket/web-client";
var websocket;
$(document).ready(function(){
connect();
});
function connect(){
websocket = new WebSocket(URL);
websocket.onopen = function(evnt) { onOpen(evnt);};
websocket.onmessage = function(evnt) { onMessage(evnt); };
websocket.onerror = function(evnt) { onError(evnt); };
}
function sendMessage() {
websocket.send($("#message").val());
}
function onOpen() {
updateStatus("connected");
}
function onMessage(evnt) {
if (typeof evnt.data == "string") {
$("#received_messages").append(
$('<tr/>')
.append($('<td/>').text("1"))
.append($('<td/>').text(evnt.data.substring(0,evnt.data.indexOf(":"))))
.append($('<td/>').text(evnt.data.substring(evnt.data.indexOf(":")+1))));
}
}
function onError(evnt) {
alert('ERROR: ' + evnt.data);
}
function updateStatus(status){
if(status == "connected"){
$("#status").removeClass (function (index, css) {
return (css.match (/\blabel-\S+/g) || []).join(' ');
});
$("#status").text(status).addClass("label-success");
}
}
My guess is...
Since you ServerEndpoint maps an argument "{client-id}" it should be present in the URL your client uses to connect.
Either you remove the parameter on server-side or you need to include a value to it on client-side.
Again, just guessing. It would be useful if you include more information regarding the issue (e.g., server logs)
[]s
Heleno

java.net.connectexception connection timeout

hi i am using this codes for rmi
RmiServer.java
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.net.*;
public class RmiServer extends java.rmi.server.UnicastRemoteObject
implements ReceiveMessageInterface
{
int thisPort;
String thisAddress;
Registry registry; // rmi registry for lookup the remote objects.
// This method is called from the remote client by the RMI.
// This is the implementation of the gReceiveMessageInterfaceh.
public void receiveMessage(String x) throws RemoteException
{
System.out.println(x);
}
public RmiServer() throws RemoteException
{
try{
// get the address of this host.
thisAddress= (InetAddress.getLocalHost()).toString();
}
catch(Exception e){
throw new RemoteException("can't get inet address.");
}
thisPort=3232; // this port(registryfs port)
System.out.println("this address="+thisAddress+",port="+thisPort);
try{
// create the registry and bind the name and object.
registry = LocateRegistry.createRegistry( thisPort );
registry.rebind("rmiServer", this);
}
catch(RemoteException e){
throw e;
}
}
static public void main(String args[])
{
try{
RmiServer s=new RmiServer();
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}
RmiClient.java
import java.rmi.*;
import java.rmi.registry.*;
import java.net.*;
public class RmiClient
{
static public void main(String args[])
{
ReceiveMessageInterface rmiServer;
Registry registry;
String serverAddress=args[0];
String serverPort=args[1];
String text=args[2];
System.out.println("sending "+text+" to "+serverAddress+":"+serverPort);
try{
// get the �gregistry�h
registry=LocateRegistry.getRegistry(
serverAddress,
(new Integer(serverPort)).intValue()
);
// look up the remote object
rmiServer=
(ReceiveMessageInterface)(registry.lookup("rmiServer"));
// call the remote method
rmiServer.receiveMessage(text);
}
catch(RemoteException e){
e.printStackTrace();
}
catch(NotBoundException e){
e.printStackTrace();
}
}
}
ReceiveMessageInterface.java
import java.rmi.*;
public interface ReceiveMessageInterface extends Remote
{
public void receiveMessage(String x) throws RemoteException;
}
This works fine normally , but when the a computer is connected to internet through mobile or it shares internet from other pc it doesn't work
I get this error.
java.net.connectexception connection timeout
when i tried to telnet it fails to connect but when i try to run this program that pc
to my pc it works.
Please let me know how to solve this issue.
Sounds like a firewall or proxy server issue.

Categories