java - WebSocket RemoteEndpoint 不可用将数据发送回客户端的问题

标签 java eclipse websocket

我正在尝试创建类似node-websockify的东西,它基本上是一个简单的代理服务器,用于将数据从novnc服务器传输到novnc客户端,我正在使用提到的here方法

我在将 ByteBuffer 发送到远程客户端时发生奇怪的错误。 正如之前所说,客户端是一个 noVNC 客户端,node-websockifytightvnc 完美运行


import org.eclipse.jetty.websocket.server.WebSocketHandler;



org.eclipse.jetty.server.Server serverr = new org.eclipse.jetty.server.Server(8090);            
WebSocketHandler wsh = new WebSockify();
serverr.setHandler(wsh);
serverr.start();
serverr.join();


import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.server.WebSocketHandler;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebSocket
public class WebSockify extends WebSocketHandler {

    private static String authorizationHeader = "";

    Socket vncSocket;
    int vncPort = 5900;
    String vncPassword = "1234560";

    @Override
    public void configure(WebSocketServletFactory webSocketServletFactory) {
        webSocketServletFactory.register(WebSockify.class);
    }

    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

        System.out.println("Received handle " + target);
        try {
            if (this.getWebSocketFactory().isUpgradeRequest(request, response)) {
                System.out.println("Adding header");

                response.addHeader("Sec-WebSocket-Protocol", "binary");

                if (this.getWebSocketFactory().acceptWebSocket(request, response)) {

                    System.out.println("websocket accepted");
                    baseRequest.setHandled(true);

                    return;
                }
                System.out.println("websocket not accepted");
                if (response.isCommitted()) {
                    System.out.println("response commited.");
                    return;
                }
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        } finally {
            super.handle(target, baseRequest, request, response);
        }
    }

    @OnWebSocketConnect
    public void onConnect(final Session session) throws IOException, InterruptedException {
        System.out.println("Connect: " + session.getRemoteAddress().getAddress());
        System.out.println(session.getUpgradeRequest().getRequestURI());        

        System.out.println("session open ? " + session.isOpen());
        vncSocket = new Socket("127.0.0.1", vncPort);
        Thread readThread = new Thread(new Runnable() {
            public void run() {
                try {
                    System.out.println("session open ? " + session.isOpen());
                    byte[] b = new byte[1500];
                    int readBytes;
                    while (true) {
                        readBytes = vncSocket.getInputStream().read(b);
                        System.out.println("session open ? " + session.isOpen());
                        System.out.println("read bytes " + readBytes + ", " + new String(b));
                        if (readBytes == -1) {
                            break;
                        }
                        if (readBytes > 0) {
                            System.out.println("session open ? " + session.isOpen());
                            ByteBuffer bb = ByteBuffer.wrap(b, 0, readBytes);
                            session.getRemote().sendBytes(bb);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    System.err.println(e);
                }
            }
        });
        readThread.start();

    }

    @OnWebSocketFrame
    public void onFrame(Frame f) throws IOException {
        System.out.printf("Frame: %d\n", f.getPayloadLength());
        byte[] data = new byte[f.getPayloadLength()];
        f.getPayload().get(data);
        vncSocket.getOutputStream().write(data);
    }

    @OnWebSocketError
    public void onError(Throwable cause) {
        System.err.println(cause.getMessage());
    }
}

错误和控制台输出是

session 开放?正确

线程“Thread-8”org.eclipse.jetty.websocket.api.WebSocketException 中出现异常:RemoteEndpoint 不可用,当前状态 [CLOSED],期待 [OPEN 或 CONNECTED] 在 org.eclipse.jetty.websocket.common.WebSocketSession.getRemote(WebSocketSession.java:308) 在 com.hossein.main.WebSockify$1.run(WebSockify.java:91) 在 java.lang.Thread.run(来源未知)

看起来 session.open() 返回 true,但下一行 session.getRemote().sendBytes() 会导致错误。 你能帮我找出原因吗?

发现了一些东西,当我在线程内使用 session 时会出现问题,我的意思是如果我不创建新线程session.getRemote().sendBytes() 工作正常。

最佳答案

与线程无关,实际上是客户端和服务器之间握手错误造成的

public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

        System.out.println("Received handle " + target);
        try {
            if (this.getWebSocketFactory().isUpgradeRequest(request, response)) {
                System.out.println("Adding header");

                 // NO NEED, the client already put this header in the request
                //so no need to be added again
                //response.addHeader("Sec-WebSocket-Protocol", "binary");

                if (this.getWebSocketFactory().acceptWebSocket(request, response)) {

                    System.out.println("websocket accepted");
                    baseRequest.setHandled(true);

                    return;
                }
                System.out.println("websocket not accepted");
                if (response.isCommitted()) {
                    System.out.println("response commited.");
                    return;
                }
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        } finally {
             // has to be removed, because this cause an Upgrade header to be added with is already existed and causes .
            //super.handle(target, baseRequest, request, response);
        }
    }

关于java - WebSocket RemoteEndpoint 不可用将数据发送回客户端的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62403293/

相关文章:

java - 如何在Java代码中迭代第一个子节点是否匹配移动到下一个节点

java - 了解 readResolve 方法

java - 如何使用 Java 禁用 Eclipse 的自动完成功能?

java - 使用 Eclipse 进行 GWT 代码验证

java - 如何使用Java监听某个端口?

java - Cucumber:许多示例行 VS 许多场景轮廓

java - 读取 java 源文件时使用什么字符集?

android - 应用程序在调试器模式下运行,调试器不会连接

python - Django Channels 2.0 channel_layers 不通信

apache - 使用 nginx 作为反向代理运行 Apache Zeppelin