Java server JavaScript client WebSockets
Asked Answered
E

1

11

I'm trying to do a connection between a server in Java and a JavaScript client but I'm getting this error on client side:

WebSocket connection to 'ws://127.0.0.1:4444/' failed: Connection closed before receiving a handshake response

It maybe stays on OPENNING state because the connection.onopen function is never called. The console.log('Connected!') isn't being called.

Could someone let me know what is going wrong here?

Server

import java.io.IOException;
import java.net.ServerSocket;

public class Server {

    public static void main(String[] args) throws IOException {

        try (ServerSocket serverSocket = new ServerSocket(4444)) {
            GameProtocol gp = new GameProtocol();

            ServerThread player= new ServerThread(serverSocket.accept(), gp);
            player.start();

        } catch (IOException e) {
            System.out.println("Could not listen on port: 4444");
            System.exit(-1);
        }

    }

}

ServerThread

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ServerThread extends Thread{

    private Socket socket = null;
    private GameProtocol gp;

    public ServerThread(Socket socket, GameProtocol gp) {
        super("ServerThread");
        this.socket = socket;
        this.gp = gp;
    }

    public void run() {

        try (
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(
                                socket.getInputStream()));
                ) {
            String inputLine, outputLine;

            while ((inputLine = in.readLine()) != null) {
                outputLine = gp.processInput(inputLine);
                System.out.println(outputLine);
            }
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

GameProtocol

public class GameProtocol {

    public String processInput(String theInput) {

        String theOutput = null;

        theOutput = theInput;

        return theOutput;
    }
}

Client

var connection = new WebSocket('ws://127.0.0.1:4444');

connection.onopen = function () {
    console.log('Connected!');
    connection.send('Ping'); // Send the message 'Ping' to the server
};

// Log errors
connection.onerror = function (error) {
    console.log('WebSocket Error ' + error);
};

// Log messages from the server
connection.onmessage = function (e) {
    console.log('Server: ' + e.data);
};
Eisen answered 4/1, 2017 at 18:7 Comment(11)
I tried it and it worked just fine... What browser do you use for your test? Also, is there any firewall that could block/mess with the response?Photoemission
I'm using Chrome 55. I thing not. Plus, if I print out the response on server side I got the message I put above.Eisen
All seems ok... Maybe, try another port? Like 12000 or higher, I heard that some systems don't like low port numbers... I'm just speculating, because I have no idea what could be the difference between our set-ups...Photoemission
I've tried your suggestion but the problem keeps the same. You tried in Chrome and it's not printing the WebSocket error?Eisen
Yes, I'm using chrome Version 54.0.2840.71 m (64-bit) and I started my server in eclispe and when I load the page with my script, the server writes: "A client connected."Photoemission
Ok, but it's on the server side. On client side, if you go to the chrome console on chrome dev tools doesn't appear the WebSocket error?Eisen
Oh, you said in your question that you have an error on the server side... I'll try it later and tell you if i get an error in chrome.Photoemission
I've edited the post. I've made some changes on code and now the error is different. ThanksEisen
Have you checked if your local computer firewall is allowing this portCalzada
I haven't a firewall. I thing the client is waiting a response from the server and it's not receiving it. Am I right? And so it won't change the state from OPENNINGEisen
I will give it try tomorrow as it is late night for me and let you knowCalzada
C
13

To start with, both your code looks identical the Java and JavaScript one. Both work for what they are design to, but the facts is that you are trying to connect a WebSocket client to a socket server.

As I know they are two different things regarding this answer.

I have never tried it your way. That said if I have a network application that use socket than it would be pure client/server socket, and if it was a web application than I would use WebSocket on both side as well.

So far so good..

To make this work, this answer suggests to use any available WebSocket on server side and your problem is solved.

I am using WebSocket for Java and here is a sample implementation that I have tested with your client code and it works, both on client and server side.

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

import java.net.InetSocketAddress;
import java.util.HashSet;
import java.util.Set;

public class WebsocketServer extends WebSocketServer {

    private static int TCP_PORT = 4444;

    private Set<WebSocket> conns;

    public WebsocketServer() {
        super(new InetSocketAddress(TCP_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("Message from client: " + message);
        for (WebSocket sock : conns) {
            sock.send(message);
        }
    }

    @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());
    }
}

On your main method just:

new WebsocketServer().start();

You might need to manipulate your code to fit it with this implementation, but that should be part of the job.

Here is the test output with 2 tests:

New connection from 127.0.0.1
Message from client: Ping
Closed connection to 127.0.0.1
New connection from 127.0.0.1
Message from client: Ping

here is WebSocket maven configuration, otherwise download the JAR file/s manually and import it in your IDE/development environment:

<!-- https://mvnrepository.com/artifact/org.java-websocket/Java-WebSocket -->
<dependency>
    <groupId>org.java-websocket</groupId>
    <artifactId>Java-WebSocket</artifactId>
    <version>1.3.0</version>
</dependency>

Link to WebSocket.

Calzada answered 5/1, 2017 at 8:52 Comment(4)
That website isn't up anymore. Is there any way to find that API elsewhere? @maytham-ɯɐɥʇʎɐɯ Thanks!Melt
@JaredScarito here is the link github.com/TooTallNate/Java-WebSocket I do not know why the site is down, but if you use maven it gone make your day smoother. good luckCalzada
@maytham-ɯɐɥʇʎɐɯ You're awesome! Thanks so much!Melt
I have been struggling with this for days. THANK YOUSanctum

© 2022 - 2024 — McMap. All rights reserved.