I created a simple chat server in Java with a Javascript client , but I'm having a problem receiving messages from JavaScript to Java.
When i use the Java client it is work fine, but when i use Javascript i have the problem.
My code:
Java
public class ChatRunner {
public static void main(String[] args) throws Exception {
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler(
ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
try {
ServerContainer wscontainer = WebSocketServerContainerInitializer
.configureContext(context);
wscontainer.addEndpoint(ChatEndpoint.class);
server.start();
server.dump(System.err);
server.join();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
#ServerEndpoint(value="/events/")
public class ChatEndpoint {
#OnOpen
public void onWebSocketConnect(Session sess) {
System.out.println("Socket Connected: " + sess);
}
#OnMessage
public void onWebSocketText(String message) {
System.out.println("Received TEXT message: " + message);
}
#OnClose
public void onWebSocketClose(CloseReason reason) {
System.out.println("Socket Closed: " + reason);
}
#OnError
public void onWebSocketError(Throwable cause) {
cause.printStackTrace(System.err);
}
}
JavaScript:
var ws = new WebSocket("ws://localhost:8080/events/");
ws.onopen = function() { ws.send("Hello"); };
Well you can test your server using https://www.websocket.org/echo.html. Simply put your global url and test.
Related
I need help with connect on android to my WebSocket server based on Spring boot. Source code of this server I have taken https://spring.io/guides/gs/messaging-stomp-websocket/
Everything works fine on server and browser client on this sample,
but if I use StompClient (https://github.com/NaikSoftware/StompProtocolAndroid) to connect on my socket I am getting mStompClient.isConnected() == false and conand mStompClient.send(...) doesn't send anything (?).
After few minutes socketweb server closes the connection and I get in my log: '~~ Stomp connection closed'.
Web server locates on Heroku cloud system.
There is my connecting code from android activity:
private StompClient mStompClient;
private void connectStomp(){
mStompClient = Stomp.over(WebSocket.class, "wss://myserver/gs-guide-websocket");
mStompClient.topic("/topic/greetings").subscribe(new Action1<StompMessage>() {
#Override
public void call(StompMessage stompMessage) {
Log.w(TAG, "== "+stompMessage.getPayload());
}
});
mStompClient.connect();
mStompClient.lifecycle().subscribe(new Action1<LifecycleEvent>() {
#Override
public void call(LifecycleEvent lifecycleEvent) {
switch (lifecycleEvent.getType()) {
case OPENED:
Log.w(TAG, "~~ Stomp connection opened");
break;
case ERROR:
Log.e(TAG, "~~ Error", lifecycleEvent.getException());
break;
case CLOSED:
Log.w(TAG, "~~ Stomp connection closed "+lifecycleEvent.getMessage());
break;
}
}
});
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
connectStomp();
}
// Send test request to server
public void onSend(View view){
Log.w(TAG,"onSend: click");
mStompClient.send("/app/hello","Test").subscribe(new Observer<Void>() {
#Override
public void onCompleted() {
Log.w(TAG, "~~~~ onCompleted");
}
#Override
public void onError(Throwable e) {
Log.w(TAG, "~~~~ onCompleted "+e.getMessage());
}
#Override
public void onNext(Void aVoid) {
Log.w(TAG, "~~~~ onNext ");
}
});
if (mStompClient.isConnected()){
mStompClient.send("/app/hello","test msg").subscribe();
Log.w("aaaa : ","onCreate: connected");
}
}
It would be my mistake but if I connect to my server socket with spring boot WebSocketStompClient everithing works fine:
private SockJsClient sockJsClient;
private WebSocketStompClient stompClient;
private final WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
#Before
public void setup() {
List<Transport> transports = new ArrayList<>();
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
this.sockJsClient = new SockJsClient(transports);
this.stompClient = new WebSocketStompClient(sockJsClient);
this.stompClient.setMessageConverter(new MappingJackson2MessageConverter());
}
#Test
public void getGreeting() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<Throwable> failure = new AtomicReference<>();
StompSessionHandler handler = new TestSessionHandler(failure) {
#Override
public void afterConnected(final StompSession session, StompHeaders connectedHeaders) {
session.subscribe("/topic/greetings", new StompFrameHandler() {
#Override
public Type getPayloadType(StompHeaders headers) {
return Greeting.class;
}
#Override
public void handleFrame(StompHeaders headers, Object payload) {
Greeting greeting = (Greeting) payload;
try {
System.out.println(greeting.getContent());
assertEquals("Hello, Spring!", greeting.getContent());
} catch (Throwable t) {
System.out.println(t.getMessage());
failure.set(t);
} finally {
session.disconnect();
latch.countDown();
}
}
});
try {
session.send("/app/hello", "Test");
} catch (Throwable t) {
failure.set(t);
latch.countDown();
}
}
};
this.stompClient.connect("wss://myserver/gs-guide-websocket", this.headers, handler, 443);
if (latch.await(10, TimeUnit.SECONDS)) {
if (failure.get() != null) {
throw new AssertionError("", failure.get());
}
}
else {
fail("Greeting not received");
}
}
private class TestSessionHandler extends StompSessionHandlerAdapter {
private final AtomicReference<Throwable> failure;
public TestSessionHandler(AtomicReference<Throwable> failure) {
this.failure = failure;
}
#Override
public void handleFrame(StompHeaders headers, Object payload) {
this.failure.set(new Exception(headers.toString()));
}
#Override
public void handleException(StompSession s, StompCommand c, StompHeaders h, byte[] p, Throwable ex) {
this.failure.set(ex);
}
Any ideas? Thanks a lot!
I used the same Library in order to connect with Stomp based web socket. There were some configurations on the server side. On the android side, I was using URL as starting with "ws://" and ending with "websocket" like "ws://" + SERVER_URL + "/websocket".
See this answer for server side https://stackoverflow.com/a/41751897/5392825
I have a Java EE Endpoint set up on a Payara server to which I attempt to connect an Android client using Autobahn WebSockets. I have the following setup:
My WebSocket Endpoint on the server:
public class CommunicationSocket extends Endpoint {
#Override
public void onOpen(Session aSession, EndpointConfig aConfig) {
aSession.addMessageHandler(new MessageHandler.Whole<byte[]>() {
#Override
public void onMessage(byte[] aMessage) {
// Do something fun
}
});
}
}
I register the WebSocket as such:
public class RegisterSocket implements ServerApplicationConfig {
#Override
public Set<ServerEndpointConfig> getEndpointConfigs(
Set<Class<? extends Endpoint>> aEndpointClasses) {
Set<ServerEndpointConfig> result = new HashSet<>();
for (Class endpointClass : aEndpointClasses) {
if (endpointClass.equals(CommunicationSocket.class)) {
ServerEndpointConfig sec
= ServerEndpointConfig.Builder.create(endpointClass,
"/WebSocket").build();
result.add(sec);
}
}
return result;
}
#Override
public Set<Class<?>> getAnnotatedEndpointClasses(
Set<Class<?>> aScanned) {
return Collections.emptySet();
}
}
The WebSocket can now be reached att ws://localhost:46588/Server/WebSocket. I've confirmed that it works with the following javascript in chrome:
function WebSocketTest() {
if ("WebSocket" in window) {
ws = new WebSocket("ws://localhost:46588/Server/WebSocket");
ws.onopen = function() {
ws.send("Message to send");
alert("Message is sent...");
};
ws.onmessage = function (evt) {
var received_msg = evt.data;
alert("Message is received... \n" + received_msg);
};
} else {
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!");
}
}
However when I try to connect with my android client using autobahn, the socket closes without being able to establish a connection with the message "Connection refused". I use the following code in onCreate to connect (mSocket is a field of the activity class):
WebSocketHandler messageHandler = new WebSocketHandler() {
#Override
public void onOpen() {
System.out.println("Connected...");
}
#Override
public void onClose(int code, String reason) {
System.out.println("Socket closing: " + reason);
mSocket = null;
}
#Override
public void onTextMessage(String payload) {
System.out.println("Received: " + payload);
}
#Override
public void onBinaryMessage(byte[] payload) {
System.out.println("Message received: " + payload);
}
};
mSocket = new WebSocketConnection();
try {
String address = "ws://localhost:46588/Server/WebSocket";
mSocket.connect(address, messageHandler);
} catch (WebSocketException e) {
System.out.println("Could not connect to WebSocket: "
+ e.getMessage());
mSocket = null;
}
I have internet permissions i my manifest as so:
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
Is there anything in my code or approach that is wrong? Is it possible to log/catch the event of connecting (handshake or what not) in order to shed light onto why the connection is refused?
And as I got ready to post the question I googled one last time: lo and behold, localhost is not the localhost of the machine running the emulator (I guess it's the localhost of the emulated device). So use:
10.0.2.2:[port]
instead of
localhost:[port]
and it will be fine on the emulator (don't forget to change if running on an actual device)
I have the following web-socket server code from (https://github.com/TooTallNate/Java-WebSocket):
public class WebsocketServer extends WebSocketServer {
private static int PORT = 2005;
private Set<WebSocket> conns;
public WebsocketServer() {
super(new InetSocketAddress(PORT));
conns = new HashSet<>();
}
#Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
conns.add(conn);
System.out.println("New connection from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
#Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
conns.remove(conn);
System.out.println("Closed connection to " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
#Override
public void onMessage(WebSocket conn, String message) {
System.out.println("Received: " + message);
for (WebSocket sock : conns) {
sock.send(messageToSend);
}
}
#Override
public void onError(WebSocket conn, Exception ex) {
ex.printStackTrace();
if (conn != null) {
conns.remove(conn);
// do some thing if required
}
System.out.println("ERROR from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
public static void main(String[] args) throws IOException, InterruptedException {
WebsocketServer server = new WebsocketServer();
server.run();
BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String in = sysin.readLine();
server.sendToAll(in);
if (in.equals("exit")) {
server.stop();
break;
} else if (in.equals("restart")) {
server.stop();
server.start();
break;
}
}
}
public void sendToAll(String text) {
Collection<WebSocket> con = connections();
synchronized (con) {
for (WebSocket c : con) {
c.send(text);
}
}
}
}
The codes works fine, but all codes that comes after server.run(); won't start/work! that part I need to send messages from Java console to client.
What I am doing wrong?
Note: My client works in JavaScript and can connect to the server
You need to start() Runnable class, not run() it directly
server.start();
instead of
server.run();
I'm using websocket in the client side (javascript) and in the server side a java class.
This is my WordgameServerEndpoint side class
#ServerEndpoint(value = "/socket")
public class WordgameServerEndpoint {
private Logger logger = Logger.getLogger(this.getClass().getName());
#OnOpen
public void onOpen(Session session) {
logger.info("Connected ... " + session.getId());
}
#OnMessage
public String onMessage(String unscrambledWord, Session session) {
logger.info("Starting the game by sending first word");
return unscrambledWord;
}
#OnClose
public void onClose(Session session, CloseReason closeReason) {
logger.info(String.format("Session %s closed because of %s", session.getId(), closeReason));
}
}
This is the WebSocketServer class
public class WebSocketServer {
public static void main(String[] args) {
runServer();
}
public static void runServer() {
Server server = new Server("localhost", 9988, "/websockets", WordgameServerEndpoint.class);
try {
server.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Please press a key to stop the server.");
//reader.readLine();
System.out.println(reader.readLine());
} catch (Exception e) {
e.printStackTrace();
} finally {
server.stop();
}
}
}
and this is my javascript function to send message
$scope.savedata=function(){
socket= new WebSocket('ws://majed-PC:9988/websockets/socket');
socket.onopen= function() {
socket.send('hello');
};
};
How do I get the value of the sent message on the server side?
See
#OnMessage
public String onMessage(String unscrambledWord, Session session) {
logger.info("Starting the game by sending first word");
return unscrambledWord;
}
on server side. unscrambledWord is the received message. Your implementation just echoes it back, which might not be what you want to do - just place your logic there.
I'm new to Jerry, and trying to implement WebSocket Client on Jetty9.
I saw an example on Jetty8.
org.eclipse.jetty.websocket Class WebSocketClient
http://archive.eclipse.org/jetty/8.0.0.v20110901/apidocs/org/eclipse/jetty/websocket/WebSocketClient.html
to create a new instance of WebSocketClient is :
WebSocketClientFactory factory = new WebSocketClientFactory();
factory.start();
WebSocketClient client = factory.newWebSocketClient();
// Configure the client
WebSocket.Connection connection = client.open(new
URI("ws://127.0.0.1:8080/"), new WebSocket.OnTextMessage()
{
public void onOpen(Connection connection)
{
// open notification
}
public void onClose(int closeCode, String message)
{
// close notification
}
public void onMessage(String data)
{
// handle incoming message
}
}).get(5, TimeUnit.SECONDS);
connection.sendMessage("Hello World");
However, I've never seen a document for Jetty9 for this.
So far, referring to
org.eclipse.jetty.websocket.common
Interface SessionFactory
//----------------------------------------------
WebSocketSession createSession(URI requestURI,
EventDriver websocket,
LogicalConnection connection)
//----------------------------------------------
I've tried
private WebSocketSessionFactory factory = new WebSocketSessionFactory();
try
{
WebSocketSession session = factory.createSession(uri,
eventDriver, connection);
RemoteEndpoint ep = session.getRemote();
}
catch (Exception ex)
{
System.out.println("=ERROR= " + ex);
//=ERROR= java.lang.NullPointerException
}
private EventDriver eventDriver = new EventDriver()
{
#Override
public WebSocketPolicy getPolicy()
{
return null;
}
//......................................
#Override
public void incomingFrame(Frame frame)
{
}
};
private LogicalConnection connection = new LogicalConnection()
{
#Override
public void close()
{
}
//...............................
#Override
public void resume()
{
}
};
but I've encounter java.lang.NullPointerException
How do we implement Jetty9 WebSocket Client ??
Thanks for your advise.
Hope this helpful: EventClient.java