简体   繁体   中英

Java Server, html client, unable to send messages to server

i got a little problem with my project. I have a Server written in Java and some clients written in html/js. Connecting works somehow, but as soon as i want to send a message from the client to the server it returns an error: "Uncaught InvalidStateError: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state"

Hopefully some of you awesome guys can look over my code and help me :)

Server Code:

Server.java

public class Server {

static ArrayList<Clients> clientsArrayList = new ArrayList<>();
private static int clientCount = 1;
private static int port;
private static ServerSocket ss;
private Socket socket;
private Clients clienthandler;
static boolean isRunning = true;

public Server(int port) throws IOException {

    this.port = port;
    setSs(new ServerSocket(port));
}

public void run() throws IOException {

    while (isRunning) {

        log("Listening on " + port + "...");
        socket = getSs().accept();
        log("Receiving client... " + socket);

        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));        
        PrintWriter out = new PrintWriter(socket.getOutputStream());

        String s;
        while ((s = in.readLine()) != null) {
            log(s);
            if (s.isEmpty()) {
                break;
            }
        }

        log("Creating a new handler for this client...");

        clienthandler = new Clients(socket, "Client " + clientCount, in, out);
        Thread t = new Thread(clienthandler);

        clientsArrayList.add(clienthandler);
        log("Added to client list");
        t.start();
        clientCount++;

        GUI.texttoclientlog();
    }

}

public static ServerSocket getSs() {
    return ss;
}

public static void setSs(ServerSocket ss) {
    Server.ss = ss;
}

public void log(String logtext) {
    System.out.println(logtext);
    GUI.texttolog(logtext);

}

}

Clients.java

public class Clients implements Runnable {

private String name;
final BufferedReader in;
final PrintWriter out;
Socket socket;
boolean isloggedin;

public Clients(Socket socket, String name, BufferedReader in, PrintWriter out) {

    this.out = out;
    this.in = in;
    this.name = name;
    this.socket = socket;
    this.isloggedin = true;
}

@Override
public void run() {

    String received;
    while (true) {
        try {
            // receive the string
            received = in.readLine();

            System.out.println(received);

            GUI.messagehandler(this.getName() + ": " + received);

            if (received.equals("logout")) {
                this.isloggedin = false;
                this.socket.close();
                break;
            }

            this.in.close();
            this.out.close();
            this.out.flush();
            this.out.flush();

        } catch (IOException e) {
            e.printStackTrace();

        }

    }
}

public String getName() {
    return name;

}

}

And the JS client code:

    <script>
  var connection;

  connection = new WebSocket("ws://localhost:6788/");
  console.log("connection established");

  connection.onmessage = function (e) { console.log(e.data); };
  connection.onopen = () => conn.send("Connection established");
  connection.onerror = function (error) {
    console.log("WebSocket Error" + error);
  };

  function Send() {
    if (connection.readyState === 1) {
      connection.send("test");
    }
        console.log("error sending");
    }

</script>

The WebSocket session is established via a handshake . Post the handshake is complete and the connection is upgraded, the server and client can send messages. Here is a sample WebSocket server in Java.

Update the clients run method to

public void run() {

    int len = 0;            
    byte[] b = new byte[80];
    while(true){
        try {
            len = in.read(b);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if(len!=-1){

            byte rLength = 0;
            int rMaskIndex = 2;
            int rDataStart = 0;
            //b[0] is always text in my case so no need to check;
            byte data = b[1];
            byte op = (byte) 127;
            rLength = (byte) (data & op);

            if(rLength==(byte)126) rMaskIndex=4;
            if(rLength==(byte)127) rMaskIndex=10;

            byte[] masks = new byte[4];

            int j=0;
            int i=0;
            for(i=rMaskIndex;i<(rMaskIndex+4);i++){
                masks[j] = b[i];
                j++;
            }

            rDataStart = rMaskIndex + 4;

            int messLen = len - rDataStart;

            byte[] message = new byte[messLen];

            for(i=rDataStart, j=0; i<len; i++, j++){
                message[j] = (byte) (b[i] ^ masks[j % 4]);
            }

            System.out.println(new String(message)); 

            b = new byte[80];

        }
    }
}

based on this SO answer

In my opinion you can leverage the Spring WebSocket support, rather than writing your own. I had created one which also uses ProtoBuf or you can look at the Spring WebSocket getting started guide here

Thats the updated code. it receives the bytes from the html clients. but i have no clue how to decode them :)

Server.java

public class Server {

static ArrayList<Clients> clientsArrayList = new ArrayList<>();
private static int clientCount = 1;
private static int port;
private static ServerSocket ss;
private Socket socket;
private Clients clienthandler;
static boolean isRunning = true;
private InputStream in;
private OutputStream out;

public Server(int port) throws IOException {

    Server.port = port;
    setSs(new ServerSocket(port));
}

public void run() throws IOException, NoSuchAlgorithmException {

    while (isRunning) {

        log("Listening on " + port + "...");
        socket = getSs().accept();
        log("Receiving client... " + socket);

        in = socket.getInputStream();
        out = socket.getOutputStream();


        @SuppressWarnings("resource")
        String data = new Scanner(in, "UTF-8").useDelimiter("\\r\\n\\r\\n").next();

        Matcher get = Pattern.compile("^GET").matcher(data);

        if (get.find()) {

            Matcher match = Pattern.compile("Sec-WebSocket-Key: (.*)").matcher(data);
            match.find();
            byte[] response = ("HTTP/1.1 101 Switching Protocols\r\n" + "Connection: Upgrade\r\n"
                    + "Upgrade: websocket\r\n" + "Sec-WebSocket-Accept: "
                    + DatatypeConverter.printBase64Binary(MessageDigest.getInstance("SHA-1")
                            .digest((match.group(1) + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes("UTF-8")))
                    + "\r\n\r\n").getBytes("UTF-8");

            out.write(response, 0, response.length);

            log("Creating a new handler for this client...");

            clienthandler = new Clients(socket, "Client " + clientCount, in, out);
            Thread t = new Thread(clienthandler);

            clientsArrayList.add(clienthandler);
            log("Added to client list");
            t.start();
            clientCount++;

            GUI.texttoclientlog();

        } else {

            log("Handshake failed");

        }

    }

}

public static ServerSocket getSs() {
    return ss;
}

public static void setSs(ServerSocket ss) {
    Server.ss = ss;
}

public void log(String logtext) {
    System.out.println(logtext);
    GUI.texttolog(logtext);

}

}

Clients.java

public class Clients implements Runnable {

private String name;
final InputStream in;
final OutputStream out;
Socket socket;
boolean isloggedin;

public Clients(Socket socket, String name, InputStream in, OutputStream out) {

    this.out = out;
    this.in = in;
    this.name = name;
    this.socket = socket;
    this.isloggedin = true;
}

@Override
public void run() {

    int received;
    while (true) {
        try {

            received = in.read();


            //how to decode??
            System.out.println(received);

            GUI.messagehandler(this.getName() + ": " + received);


        } catch (IOException e) {
            e.printStackTrace();

        }

    }
}

public String getName() {
    return name;

}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM