Java Server,html客户端,无法向服务器发送消息

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Server,html客户端,无法向服务器发送消息相关的知识,希望对你有一定的参考价值。

我的项目有点问题。我有一个用Java编写的服务器和一些用html / js编写的客户端。连接以某种方式工作,但是一旦我想从客户端向服务器发送消息,它就会返回错误:“未捕获的InvalidStateError:无法在'WebSocket'上执行'发送':仍然处于CONNECTING状态”

希望你们中的一些人能看到我的代码并帮助我:)

服务器代码:

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;

}

}

和JS客户端代码:

    <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>
答案

WebSocket会话是通过handshake建立的。握手完成并且连接升级后,服务器和客户端可以发送消息。 Here是Java中的示例WebSocket服务器。

将客户端运行方法更新为

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];

        }
    }
}

基于this SO答案

在我看来,您可以利用Spring WebSocket支持,而不是自己编写。我创建了one也使用了ProtoBuf,或者你可以看一下Spring WebSocket入门指南here

另一答案

这是更新的代码。它从html客户端接收字节。但我不知道如何解码它们:)

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
" + "Connection: Upgrade
"
                    + "Upgrade: websocket
" + "Sec-WebSocket-Accept: "
                    + DatatypeConverter.printBase64Binary(MessageDigest.getInstance("SHA-1")
                            .digest((match.group(1) + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes("UTF-8")))
                    + "

").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;

}

}

以上是关于Java Server,html客户端,无法向服务器发送消息的主要内容,如果未能解决你的问题,请参考以下文章

服务器推送浏览器:Server-Sent Events(SSE)

Java Tomcat服务器

HTML5 SSE

无法通过 websocket 从服务器向客户端发送数据

Java web-server 应用程序有没有办法推送?

HTTP Server-Push:服务到服务,无需浏览器