【问题标题】:Jetty 9 WebSocket client issue when using secure connection使用安全连接时的 Jetty 9 WebSocket 客户端问题
【发布时间】:2019-09-27 13:05:12
【问题描述】:

我正在使用 Jetty 9.4.18 库在 Java 应用程序中编写 WebSocket 客户端。

我对 WebSockets 很陌生,所以我开始使用 Jetty 文档中的两个示例类进行测试,连接到 echo.websocket.org

当我在没有 SSL 的情况下连接时测试运行良好,但如果连接到 wss://echo.websocket.org 时失败

我总是遇到同样的异常:

java.io.EOFException: HttpConnectionOverHTTP@50371e9d::DecryptedEndPoint@6dc65fc2{echo.websocket.org/174.129.224.73:443<->/192.168.1.34:60521,OPEN,fill=-,flush=C,to=226/0}
    at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.earlyEOF(HttpReceiverOverHTTP.java:338)
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1551)
    at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.shutdown(HttpReceiverOverHTTP.java:209)
    at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:147)
    at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:73)
    at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133)
    at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:155)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:411)
    at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:305)
    at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:159)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
    at java.lang.Thread.run(Thread.java:748)

服务器似乎在没有响应握手请求的情况下关闭。

我知道 SslContextFactory,但我的理解是,只有在您需要自己的 TrustStore 或 KeyStore 或其他特殊情况时才应使用它。

另请注意,在尝试失败后,我从https://github.com/TooTallNate/Java-WebSocket 下载了另一个 websocket 实现,它在 ws 和 wss 上都可以正常工作,而无需为 SSL 设置任何特定内容。 但是对于这个项目,我必须使用 Jetty。

我使用的代码正是来自 https://www.eclipse.org/jetty/documentation/9.4.x/jetty-websocket-client-api.html 的 Jetty 文档中的示例

我所做的唯一更改是向 SimpleEchoSocket 添加了一个 onError 方法,该方法会转储完整的异常堆栈。

我错过了什么吗?

提前致谢!

【问题讨论】:

    标签: java websocket jetty


    【解决方案1】:

    不幸的是,websocket.org(和 Kaazing 主机/代理)此时有一堆 TLS 问题,所以现在使用他们的公共服务器不是明智的选择。

    这是一个不同的演示,同样使用 TLS 和 WebSocket,针对具有正确和健全的 TLS/SSL 实现的 stackexchange 服务器。

    这是针对 Jetty 9.4.18.v20190429 编写的

    package org.eclipse.jetty.demo;
    
    import java.net.URI;
    import java.util.concurrent.Future;
    
    import org.eclipse.jetty.client.HttpClient;
    import org.eclipse.jetty.util.component.LifeCycle;
    import org.eclipse.jetty.util.log.Log;
    import org.eclipse.jetty.util.log.Logger;
    import org.eclipse.jetty.util.ssl.SslContextFactory;
    import org.eclipse.jetty.websocket.api.Session;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
    import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
    import org.eclipse.jetty.websocket.api.annotations.WebSocket;
    import org.eclipse.jetty.websocket.client.WebSocketClient;
    
    @WebSocket
    public class SecureClientSocket
    {
        private static final Logger LOG = Log.getLogger(SecureClientSocket.class);
    
        public static void main(String[] args)
        {
            String url = "wss://qa.sockets.stackexchange.com/";
    
            SslContextFactory ssl = new SslContextFactory.Client();
            ssl.setEndpointIdentificationAlgorithm("HTTPS");
            HttpClient http = new HttpClient(ssl);
            WebSocketClient client = new WebSocketClient(http);
            try
            {
                http.start();
                client.start();
                SecureClientSocket socket = new SecureClientSocket();
                Future<Session> fut = client.connect(socket, URI.create(url));
                Session session = fut.get();
                session.getRemote().sendString("Hello");
                session.getRemote().sendString("155-questions-active");
            }
            catch (Throwable t)
            {
                LOG.warn(t);
            }
            finally
            {
                stop(http);
                stop(client);
            }
        }
    
        private static void stop(LifeCycle lifeCycle)
        {
            try
            {
                lifeCycle.stop();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    
        @OnWebSocketConnect
        public void onConnect(Session sess)
        {
            LOG.info("onConnect({})", sess);
        }
    
        @OnWebSocketClose
        public void onClose(int statusCode, String reason)
        {
            LOG.info("onClose({}, {})", statusCode, reason);
        }
    
        @OnWebSocketError
        public void onError(Throwable cause)
        {
            LOG.warn(cause);
        }
    
        @OnWebSocketMessage
        public void onMessage(String msg)
        {
            LOG.info("onMessage() - {}", msg);
        }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-16
    • 1970-01-01
    相关资源
    最近更新 更多