0

我们正在使用 guacamole 在网络浏览器中访问远程桌面。我们尝试使用 websocket-tunnel 以获得更好的性能,但是如果我在浏览器中打开两个选项卡,通过同一个 guacd 服务器连接到两个不同的 vnc 服务器,一个页面会被冻结(websocket 停止发送/接收任何消息),另一个会出现错误,例如: 776 并断开连接。但是如果我们使用 http servlet 似乎这会得到解决。有人遇到类似的问题吗?这是我的设置。

  1. guacamole-js 用于 web 端。
  2. 我们使用 x11vnc,guacd 安装在同一个 linux 机器上
  3. 我们使用 spring-boot 开发了两个端点:websocket-tunnel 通过扩展 GuacamoleWebSocketTunnelEndpoint,

    @Component
    public class MyGuacamoleWebSocketEndPoint extends GuacamoleWebSocketTunnelEndpoint {@Autowired
    MyGuacamoleAutoProperties myGuacamoleAutoProperties;
    
    private static final Logger logger = LoggerFactory.getLogger(MyGuacamoleWebSocketEndPoint.class);
    
    public myGuacamoleWebSocketEndPoint() {
        logger.info("MyGuacamoleWebSocketEndPoint constructed!");
    }
    
    @Override
    protected GuacamoleTunnel createTunnel(Session session, EndpointConfig endpointConfig) throws GuacamoleException{
    
        Map<String, List<String>> parameterMap = session.getRequestParameterMap();
    
        String vid = getFirstValue(parameterMap,myGuacamoleAutoProperties.getVncPortParaName());
        String host = getFirstValue(parameterMap,myGuacamoleAutoProperties.getVncHostParaName());
    
        // Get client information
        GuacamoleClientInformation info = new GuacamoleClientInformation();
        // Create our configuration
        GuacamoleConfiguration config  = new GuacamoleConfiguration();
        config.setProtocol("vnc");
        config.setParameter("hostname", host);
        config.setParameter("port", vid);
        config.setParameter("password", myGuacamoleAutoProperties.getVncPassword());
    
        String guacdHost=host;
        // Connect to guacd
        GuacamoleTunnel tunnel;
        if(myGuacamoleAutoProperties.isUseStandaloneGuacd()){
            guacdHost=myGuacamoleAutoProperties.getGuacdHost();
        }
        GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
                new InetGuacamoleSocket(guacdHost,myGuacamoleAutoProperties.getGuacdPort()), config);
        tunnel=new SimpleGuacamoleTunnel(socket);
        GuacamoleTunnel monitoredTunnel = new DelemyingGuacamoleTunnel(tunnel) {
    
            @Override
            public GuacamoleReader acquireReader() {
                logger.debug("Open tunnel on port: '" + getPort() + "', uuid: '" + getUUID() + "' and connection_id: '" + ((ConfiguredGuacamoleSocket)getSocket()).getConnectionID() + "'.");
                return super.acquireReader();
            }
    
            @Override
            public void close() throws GuacamoleException {
                logger.debug("Close tunnel on port: '" + getPort() + "', uuid: '" + getUUID() + "' and connection_id: '" + ((ConfiguredGuacamoleSocket)getSocket()).getConnectionID() + "'.");
                super.close();
            }
    
            /**
             * Get the Guac Port from the Tunnel->Socket->Configuration.
             *
             * @return Guac Port
             */
            private String getPort() {
                return ((ConfiguredGuacamoleSocket) getSocket()).getConfiguration().getParameter("port");
            }
        };
    
        return monitoredTunnel;
    }
    
    private String getFirstValue(Map<String, List<String>> map, String key) {
        List<String> values = map.get(key);
        return values != null ? values.get(0) : null;
    }
    

通过扩展 GuacamoleHTTPTunnelServlet 实现 http-servlet 隧道

@Component
public class MyGuacamoleTunnelServlet extends GuacamoleHTTPTunnelServlet {

    @Autowired
    MyGuacamoleAutoProperties myGuacamoleAutoProperties;

    @Override
    protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException {
        String vid = request.getParameter(myGuacamoleAutoProperties.getVncPortParaName());
        String host = request.getParameter(myGuacamoleAutoProperties.getVncHostParaName());

        // Create our configuration
        GuacamoleConfiguration config = new GuacamoleConfiguration();
        config.setProtocol("vnc");
        config.setParameter("hostname", host);
        config.setParameter("port", vid);
        //config.setParameter("user",  request.getParameter("user"));
        config.setParameter("password", myGuacamoleAutoProperties.getVncPassword());

        // Connect to guacd
        String guacdHost=host;
        GuacamoleTunnel tunnel;
        if(myGuacamoleAutoProperties.isUseStandaloneGuacd()){
            guacdHost=myGuacamoleAutoProperties.getGuacdHost();
        }

        GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
                new InetGuacamoleSocket(guacdHost,myGuacamoleAutoProperties.getGuacdPort()), config);
        tunnel=new SimpleGuacamoleTunnel(socket);
        // Return a new tunnel which uses the connected socket
        return tunnel;
    }
}

Guacd 在这里记录:

Jan 25 04:32:58 vnchost guacd[105232]: Protocol "vnc" selected
Jan 25 04:32:58 vnchost guacd[105232]: Connection ID is "$7d545e7e-0a29-40e5-a4a3-9964fa07b22b"
Jan 25 04:32:58 vnchost guacd[105232]: VNC server supports protocol version 3.8 (viewer 3.8)
Jan 25 04:32:58 vnchost guacd[105232]: We have 1 security types to read
Jan 25 04:32:58 vnchost guacd[105232]: 0) Received security type 1
Jan 25 04:32:58 vnchost guacd[105232]: Selecting security type 1 (0/1 in the list)
Jan 25 04:32:58 vnchost guacd[105232]: Selected Security Scheme 1
Jan 25 04:32:58 vnchost guacd[105232]: No authentication needed
Jan 25 04:32:58 vnchost guacd[105232]: VNC authentication succeeded
Jan 25 04:32:58 vnchost guacd[105232]: Desktop name "vnchost:0"
Jan 25 04:32:58 vnchost guacd[105232]: Connected to VNC server, using protocol version 3.8
Jan 25 04:32:58 vnchost guacd[105232]: VNC server default format:
Jan 25 04:32:58 vnchost guacd[105232]:  32 bits per pixel.
Jan 25 04:32:58 vnchost guacd[105232]:  Least significant byte first in each pixel.
Jan 25 04:32:58 vnchost guacd[105232]:  TRUE colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0
Jan 25 04:32:58 vnchost guacd[105232]: Starting client
Jan 25 04:32:58 vnchost guacd[105232]: client2server supported messages (bit flags)
Jan 25 04:32:58 vnchost guacd[105232]: 00: 00ff 0081 0000 0000 - 0000 0000 0000 0000
Jan 25 04:32:58 vnchost guacd[105232]: 08: 0000 0000 0000 0000 - 0000 0000 0000 0000
Jan 25 04:32:58 vnchost guacd[105232]: 10: 0000 0000 0000 0000 - 0000 0000 0000 0000
Jan 25 04:32:58 vnchost guacd[105232]: 18: 0000 0000 0000 0000 - 0000 0000 0000 0004
Jan 25 04:32:58 vnchost guacd[105232]: server2client supported messages (bit flags)
Jan 25 04:32:58 vnchost guacd[105232]: 00: 001f 0080 0000 0000 - 0000 0000 0000 0000
Jan 25 04:32:58 vnchost guacd[105232]: 08: 0000 0000 0000 0000 - 0000 0000 0000 0000
Jan 25 04:32:58 vnchost guacd[105232]: 10: 0000 0000 0000 0000 - 0000 0000 0000 0000
Jan 25 04:32:58 vnchost guacd[105232]: 18: 0000 0000 0000 0000 - 0000 0000 0000 0004
Jan 25 04:32:58 vnchost guacd[105232]: Connected to Server "unknown (LibVNCServer 0.9.9)”

Jan 25 04:36:28 vnchost guacd[105538]: Protocol "vnc" selected
Jan 25 04:36:28 vnchost guacd[105538]: Connection ID is "$6fd98484-1dd0-4c66-aa04-6c358cd30548"
Jan 25 04:36:29 vnchost guacd[105538]: VNC server supports protocol version 3.8 (viewer 3.8)
Jan 25 04:36:29 vnchost guacd[105538]: We have 1 security types to read
Jan 25 04:36:29 vnchost guacd[105538]: 0) Received security type 1
Jan 25 04:36:29 vnchost guacd[105538]: Selecting security type 1 (0/1 in the list)
Jan 25 04:36:29 vnchost guacd[105538]: Selected Security Scheme 1
Jan 25 04:36:29 vnchost guacd[105538]: No authentication needed
Jan 25 04:36:29 vnchost guacd[105538]: VNC authentication succeeded
Jan 25 04:36:29 vnchost guacd[105538]: Desktop name "vnchost:2"
Jan 25 04:36:29 vnchost guacd[105538]: Connected to VNC server, using protocol version 3.8
Jan 25 04:36:29 vnchost guacd[105538]: VNC server default format:
Jan 25 04:36:29 vnchost guacd[105538]:  32 bits per pixel.
Jan 25 04:36:29 vnchost guacd[105538]:  Least significant byte first in each pixel.
Jan 25 04:36:29 vnchost guacd[105538]:  TRUE colour: max red 255 green 255 blue 255, shift red 16 green 8 blue 0
Jan 25 04:36:29 vnchost guacd[105538]: Starting client
Jan 25 04:36:29 vnchost guacd[105538]: client2server supported messages (bit flags)
Jan 25 04:36:29 vnchost guacd[105538]: 00: 00ff 0081 0000 0000 - 0000 0000 0000 0000
Jan 25 04:36:29 vnchost guacd[105538]: 08: 0000 0000 0000 0000 - 0000 0000 0000 0000
Jan 25 04:36:29 vnchost guacd[105538]: 10: 0000 0000 0000 0000 - 0000 0000 0000 0000
Jan 25 04:36:29 vnchost guacd[105538]: 18: 0000 0000 0000 0000 - 0000 0000 0000 0004
Jan 25 04:36:29 vnchost guacd[105538]: server2client supported messages (bit flags)
Jan 25 04:36:29 vnchost guacd[105538]: 00: 001f 0080 0000 0000 - 0000 0000 0000 0000
Jan 25 04:36:29 vnchost guacd[105538]: 08: 0000 0000 0000 0000 - 0000 0000 0000 0000
Jan 25 04:36:29 vnchost guacd[105538]: 10: 0000 0000 0000 0000 - 0000 0000 0000 0000
Jan 25 04:36:29 vnchost guacd[105538]: 18: 0000 0000 0000 0000 - 0000 0000 0000 0004
Jan 25 04:36:29 vnchost guacd[105538]: Connected to Server "unknown (LibVNCServer 0.9.9)"
Jan 25 04:36:29 vnchost guacd[105538]: Connection aborted
Jan 25 04:36:30 vnchost guacd[105538]: Client disconnected
Jan 25 04:36:30 vnchost kernel: guacd[105538]: segfault at 1000003f8 ip 00007fbfce7bdc24 sp 00007ffe0d31c990 error 4 in libguac-client-vnc.so.0.0.0[7fbfce7b2000+f000]
Jan 25 04:36:30 vnchost abrt-hook-ccpp: Process 105538 (guacd) of user 0 killed by SIGSEGV - dumping core
Jan 25 04:36:30 vnchost abrt-server: Executable '/usr/local/sbin/guacd' doesn't belong to any package and ProcessUnpackaged is set to 'no'
Jan 25 04:36:43 vnchost guacd[105232]: Client is not responding.
Jan 25 04:36:43 vnchost guacd[105232]: Client disconnected
Jan 25 04:36:43 vnchost kernel: guacd[105232]: segfault at 1000003f8 ip 00007fbfce7bdc24 sp 00007ffe0d31c990 error 4 in libguac-client-vnc.so.0.0.0[7fbfce7b2000+f000]
Jan 25 04:36:43 vnchost abrt-hook-ccpp: Process 105232 (guacd) of user 0 killed by SIGSEGV - ignoring (repeated crash)

申请日志在这里:

2019-01-25 12:32:58.441 DEBUG 1 --- [nio-8080-exec-6] o.a.guacamole.net.InetGuacamoleSocket    : Connecting to guacd at vnchost:4832.
2019-01-25 12:32:58.961 DEBUG 1 --- [       Thread-6] .g.b.g.w.e.MyGuacamoleWebSocketEndPoint : Open tunnel on port: '5900', uuid: '2eba77c8-2f74-42a3-8ca5-4cf882ee3653' and connection_id: '$7d545e7e-0a29-40e5-a4a3-9964fa07b22b'.

2019-01-25 12:36:28.785 DEBUG 1 --- [nio-8080-exec-2] o.a.guacamole.net.InetGuacamoleSocket    : Connecting to guacd at vnchost:4832.
2019-01-25 12:36:29.137 DEBUG 1 --- [       Thread-8] .g.b.g.w.e.MyGuacamoleWebSocketEndPoint : Open tunnel on port: '5902', uuid: '67446967-2e8e-42d7-9c73-68c2a80a270b' and connection_id: '$6fd98484-1dd0-4c66-aa04-6c358cd30548'.
2019-01-25 12:36:30.510 DEBUG 1 --- [       Thread-8] o.a.g.w.GuacamoleWebSocketTunnelEndpoint : Connection to guacd closed.

org.apache.guacamole.GuacamoleConnectionClosedException: Connection to guacd is closed.
        at org.apache.guacamole.io.ReaderGuacamoleReader.read(ReaderGuacamoleReader.java:183) ~[guacamole-common-0.9.14.jar!/:na]
        at org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint$2.run(GuacamoleWebSocketTunnelEndpoint.java:160) ~[guacamole-common-0.9.14.jar!/:na]
Caused by: java.net.SocketException: Connection reset
        at java.net.SocketInputStream.read(SocketInputStream.java:210) ~[na:1.8.0_191]
        at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[na:1.8.0_191]
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) ~[na:1.8.0_191]
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) ~[na:1.8.0_191]
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) ~[na:1.8.0_191]
        at java.io.InputStreamReader.read(InputStreamReader.java:184) ~[na:1.8.0_191]
        at org.apache.guacamole.io.ReaderGuacamoleReader.read(ReaderGuacamoleReader.java:169) ~[guacamole-common-0.9.14.jar!/:na]
        ... 1 common frames omitted
 2019-01-25 12:36:30.511 DEBUG 1 --- [       Thread-8] .g.b.g.w.e.MyGuacamoleWebSocketEndPoint : Close tunnel on port: '5902', uuid: '67446967-2e8e-42d7-9c73-68c2a80a270b' and connection_id: '$6fd98484-1dd0-4c66-aa04-6c358cd30548'.
2019-01-25 12:36:30.511 DEBUG 1 --- [       Thread-8] o.a.guacamole.net.InetGuacamoleSocket    : Closing socket to guacd.
2019-01-25 12:36:30.627 DEBUG 1 --- [nio-8080-exec-4] o.a.g.w.GuacamoleWebSocketTunnelEndpoint : Connection to guacd closed.

org.apache.guacamole.GuacamoleConnectionClosedException: Connection to guacd is closed.
        at org.apache.guacamole.io.WriterGuacamoleWriter.write(WriterGuacamoleWriter.java:64) ~[guacamole-common-0.9.14.jar!/:na]
        at org.apache.guacamole.io.WriterGuacamoleWriter.write(WriterGuacamoleWriter.java:73) ~[guacamole-common-0.9.14.jar!/:na]
        at org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint.onMessage(GuacamoleWebSocketTunnelEndpoint.java:221) ~[guacamole-common-0.9.14.jar!/:na]
        at org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint$1.onMessage(GuacamoleWebSocketTunnelEndpoint.java:129) [guacamole-common-0.9.14.jar!/:na]
        at org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint$1.onMessage(GuacamoleWebSocketTunnelEndpoint.java:125) [guacamole-common-0.9.14.jar!/:na]
        at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:394) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_191]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_191]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_191]
Caused by: java.net.SocketException: Socket closed
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:118) ~[na:1.8.0_191]
        at java.net.SocketOutputStream.write(SocketOutputStream.java:155) ~[na:1.8.0_191]
        at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221) ~[na:1.8.0_191]
        at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291) ~[na:1.8.0_191]
        at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295) ~[na:1.8.0_191]
        at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141) ~[na:1.8.0_191]
        at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229) ~[na:1.8.0_191]
        at org.apache.guacamole.io.WriterGuacamoleWriter.write(WriterGuacamoleWriter.java:58) ~[guacamole-common-0.9.14.jar!/:na]
        ... 22 common frames omitted

2019-01-25 12:36:33.068 DEBUG 1 --- [nio-8080-exec-7] o.a.g.w.GuacamoleWebSocketTunnelEndpoint : Connection to guacd closed.

org.apache.guacamole.GuacamoleConnectionClosedException: Connection to guacd is closed.
        at org.apache.guacamole.io.WriterGuacamoleWriter.write(WriterGuacamoleWriter.java:64) ~[guacamole-common-0.9.14.jar!/:na]
        at org.apache.guacamole.io.WriterGuacamoleWriter.write(WriterGuacamoleWriter.java:73) ~[guacamole-common-0.9.14.jar!/:na]
        at org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint.onMessage(GuacamoleWebSocketTunnelEndpoint.java:221) ~[guacamole-common-0.9.14.jar!/:na]
        at org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint$1.onMessage(GuacamoleWebSocketTunnelEndpoint.java:129) [guacamole-common-0.9.14.jar!/:na]
        at org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint$1.onMessage(GuacamoleWebSocketTunnelEndpoint.java:125) [guacamole-common-0.9.14.jar!/:na]
        at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:394) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-8.5.31.jar!/:8.5.31]
        at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_191]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_191]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.31.jar!/:8.5.31]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_191]
Caused by: java.net.SocketException: Socket closed
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:118) ~[na:1.8.0_191]
        at java.net.SocketOutputStream.write(SocketOutputStream.java:155) ~[na:1.8.0_191]
        at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221) ~[na:1.8.0_191]
        at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291) ~[na:1.8.0_191]
        at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295) ~[na:1.8.0_191]
        at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141) ~[na:1.8.0_191]
        at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229) ~[na:1.8.0_191]
        at org.apache.guacamole.io.WriterGuacamoleWriter.write(WriterGuacamoleWriter.java:58) ~[guacamole-common-0.9.14.jar!/:na]
        ... 22 common frames omitted
4

1 回答 1

1

我想我在这里找到了根本原因。在我之前的 websocket 实现中,我将 Spring 容器配置为使用相同的实例来处理不同的 websocket 会话,从而处理不同的 vnc 连接。这似乎导致 guacd 断开与 guacamole Web 服务器的所有套接字连接。通过更改为每个 Websocket 会话初始化一个新的 EndPoint 实例,将解决此问题。

根本原因在于由 MyGuacamoleWebSocketEndPoint 扩展的 Guacamole 的 GuacamoleWebSocketTunnelEndpoint。GuacamoleWebSocketTunnelEndpoint 使用隧道来存储当前与 guacd 进程的连接,如果我们在 Spring 中将 MyGuacamoleWebSocketEndPoint 作为一个Bean 启动并使用它来处理所有到来的 websocket 会话,那么它将导致如上所述的不可预测的行为。

@Override
@OnOpen
public void onOpen(final Session session, EndpointConfig config) {

    // Store underlying remote for future use via sendInstruction()
    remote = session.getBasicRemote();

    try {

        // Get tunnel
        **tunnel = createTunnel(session, config);**
        if (tunnel == null) {
            closeConnection(session, GuacamoleStatus.RESOURCE_NOT_FOUND);
            return;
        }

    }
    catch (GuacamoleException e) {
        logger.error("Creation of WebSocket tunnel to guacd failed: {}", e.getMessage());
        logger.debug("Error connecting WebSocket tunnel.", e);
        closeConnection(session, e.getStatus().getGuacamoleStatusCode(),
                e.getWebSocketCode());
        return;
    }
...}

实际上这是不同线程之间的典型实例共享问题。

Guacamole 的文档只提供了一个示例来实现基于 HttpServlet 的应用程序。有了基于 websocket 的应用程序,我们就靠自己了。

于 2019-01-28T02:29:06.313 回答