java 使用 websocket 的包, 连接 wss 的 websocket 失败?

使用 jar 包 , 连接 websocket, 用域名的方式连接失败, 中间有通过 nginx 转发

<dependency>
    <groupId>org.java-websocket</groupId>
    <artifactId>Java-WebSocket</artifactId>
    <version>1.5.3</version>
</dependency>

用浏览器的控制台 new Websocket(wss://域名) 已经成功

nginx 配置正常的 , 用于 websocket 的配置添加了

proxy_set_header    Upgrade             $http_upgrade;
proxy_set_header    Connection          "upgrade";
proxy_http_version 1.1;

使用 ws://域名 方式报 400 错误

用 wss://域名 方式 nginx 连请求都没收到

域名是买的, 是能通过验证的

使用 http 直接连接服务的方式是成功的

java 代码

ClientWs clientWs = new ClientWs(url);
clientWs.connect();
while (!clientWs.getReadyState().equals(ReadyState.OPEN)) {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
    }

    System.out.println("Connecting...");

    if (clientWs.getReadyState() == ReadyState.CLOSED){
        System.out.println("连接失败");
        System.exit(-1);
    }
}

System.out.println("Connected.");
public class ClientWs extends WebSocketClient {
    public ClientWs(URI serverUri) {
        super(serverUri);
        trustAllHosts(this);
    }

    public ClientWs(URI serverUri, Map<String, String> httpHeaders) {
        super(serverUri, httpHeaders);
        trustAllHosts(this);
    }

    @Override
    public void onOpen(ServerHandshake serverHandshake) {

    }

    @Override
    public void onMessage(String s) {

    }

    @Override
    public void onClose(int i, String s, boolean b) {

    }

    @Override
    public void onError(Exception e) {

    }

    static void trustAllHosts(ClientWs clientWs){
        TrustManager[] trustAllCerts =new TrustManager[]{new X509TrustManager(){

            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[]{};
            }
        }};

        try {
            SSLContext ssl = SSLContext.getInstance("TLS");
            ssl.init(null, trustAllCerts,new java.security.SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
    }
}
阅读 1.4k
avatarAI BotBETA

从你提供的信息来看,你正在使用 Java-WebSocket 库来尝试连接到一个通过 Nginx 代理的 WebSocket 服务器,但是遇到了问题。以下是一些可能的原因和解决方案:

  1. SSL/TLS 握手问题:你的 Java 代码试图通过不安全的 ws:// 协议连接到服务器,这可能导致 400 错误。你应该使用 wss:// 协议来确保连接的安全性。同时,你的 trustAllHosts 方法可能会导致 SSL/TLS 握手失败,因为它接受所有的服务器证书,包括那些可能不安全的证书。你应该检查服务器的证书是否有效,并在可能的情况下使用正确的证书。
  2. Nginx 配置问题:虽然你已经在 Nginx 配置中添加了处理 WebSocket 的相关设置,但是可能存在其他问题。你应该检查 Nginx 的错误日志,看看是否有关于 WebSocket 连接的错误信息。同时,你也应该确保 Nginx 能够正确地代理到 WebSocket 服务器。
  3. 防火墙或安全组问题:如果你的服务器部署在云环境中,可能存在防火墙或安全组规则阻止了 WebSocket 连接。你应该检查这些规则,确保它们允许 WebSocket 连接。
  4. Java-WebSocket 库版本问题:你正在使用的 Java-WebSocket 库版本是 1.5.3,这是一个相对较旧的版本。你应该尝试升级到最新版本,看看问题是否得到解决。

以下是一个修改后的 ClientWs 类,它使用默认的 SSL 上下文而不是自定义的信任所有主机的 SSL 上下文:

public class ClientWs extends WebSocketClient {
    public ClientWs(URI serverUri) {
        super(serverUri);
    }

    public ClientWs(URI serverUri, Map<String, String> httpHeaders) {
        super(serverUri, httpHeaders);
    }

    @Override
    public void onOpen(ServerHandshake serverHandshake) {
        System.out.println("Connected.");
    }

    @Override
    public void onMessage(String s) {
        System.out.println("Received message: " + s);
    }

    @Override
    public void onClose(int i, String s, boolean b) {
        System.out.println("Connection closed: " + s);
    }

    @Override
    public void onError(Exception e) {
        System.err.println("Error: " + e.getMessage());
        e.printStackTrace();
    }
}

你可以尝试使用这个修改后的类来连接 WebSocket 服务器,看看问题是否得到解决。如果问题仍然存在,你应该进一步调试你的代码和服务器配置,找出问题的根源。

1 个回答

你应该使用js来进行连接Websocket,或者使用工具,比如 http://www.jsons.cn/websocket/
或者新版的postman是能支持Websocket,浏览器直接访问ws是不行的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题