You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java连接wss协议WebSocket遇异常,求解决方案及示例代码

Java连接TradingView WebSocket获取图表数据的问题与解决思路

问题背景

我尝试在Java中建立WebSocket连接至wss://data.tradingview.com/socket.io/websocket?from=chart%2F&date=2023_01_26-12_41&type=chart,以获取历史及实时图表数据。查阅多篇资料后仍对连接流程感到困惑,修改示例代码后遇到以下错误。

测试代码

基于示例修改的代码如下:

import java.io.IOException;
import java.net.URI;

import javax.websocket.*;

@ClientEndpoint
public class ExampleTest2 {

    Session session;

   //Problem resolved, this original echo server is no longer operational
    //private final static String url = "ws://echo.websocket.org:80";
    private final static String url = "wss://websocket-echo.com:443/";

    public static void main(String[] args) throws Exception, IOException {
        WebSocketContainer container = ContainerProvider.getWebSocketContainer();
        System.out.println("connecting...");
        container.connectToServer(ExampleTest2.class,
                URI.create(url));
        
        System.out.println("Press ENTER key to exit.");
        System.in.read();
    }


    @OnMessage
    public void newMessage(String message, Session session) {
        System.out.println(message);
    }
    @OnOpen
    public void newConnection(Session session) throws IOException {
        this.session = session;
        System.out.println("The connection has been started");
        session.getBasicRemote().sendText("hello");

    }
    @OnClose
    public void disconnection() {
        System.out.println("The connection has been ended");
    }
}

遇到的错误

错误1:缺少WebSocket实现类

运行后抛出异常:

Exception in thread "main" java.lang.RuntimeException: Could not find an implementation class.
    at javax.websocket.ContainerProvider.getWebSocketContainer(ContainerProvider.java:73)
    at ExampleTest2.main(ExampleTest2.java:14)

错误2:握手失败

添加tyrus-standalone-client-2.1.2库后,出现握手错误:

Exception in thread "main" jakarta.websocket.DeploymentException: Handshake error.
    at org.glassfish.tyrus.client.ClientManager$3$1.run(ClientManager.java:658)
    at org.glassfish.tyrus.client.ClientManager$3.run(ClientManager.java:696)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:849)
    at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
    at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:493)
    at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:299)
    at ExampleTest2.main(ExampleTest2.java:19)
Caused by: org.glassfish.tyrus.core.HandshakeException: Response code was not 101: 200.
    at org.glassfish.tyrus.client.TyrusClientEngine.processResponse(TyrusClientEngine.java:301)
    at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleHandshake(GrizzlyClientFilter.java:323)
    at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleRead(GrizzlyClientFilter.java:292)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:88)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:246)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:178)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:118)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:96)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:51)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:510)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:82)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:83)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:101)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:535)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:515)
    at java.base/java.lang.Thread.run(Thread.java:832)

解决思路与代码示例

1. 依赖版本适配

tyrus 2.x使用Jakarta WebSocket API(jakarta.websocket.*),而你的代码基于Javax(javax.websocket.*),版本不匹配会导致异常。可二选一:

  • 若保留Javax API,使用tyrus 1.x版本(如tyrus-standalone-client-1.17)
  • 若升级到Jakarta API,修改代码导入路径为jakarta.websocket.*,继续使用tyrus 2.x

2. 适配Socket.IO协议

TradingView的WebSocket基于Socket.IO协议,并非标准WebSocket,直接用Javax/Jakarta WebSocket客户端无法处理其握手逻辑和消息格式。需使用支持Socket.IO的Java客户端库,推荐socket.io-client-java。

依赖配置(Maven)

<dependency>
    <groupId>io.socket</groupId>
    <artifactId>socket.io-client</artifactId>
    <version>2.1.0</version>
</dependency>

连接示例代码

import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import org.json.JSONObject;

import java.net.URISyntaxException;

public class TradingViewSocketClient {

    public static void main(String[] args) throws URISyntaxException {
        // 配置Socket.IO连接参数
        IO.Options options = new IO.Options();
        options.transports = new String[]{"websocket"}; // 强制使用WebSocket传输
        options.reconnection = true;

        // 初始化连接
        Socket socket = IO.socket("wss://data.tradingview.com/socket.io/?from=chart%2F&date=2023_01_26-12_41&type=chart", options);

        // 监听连接成功事件
        socket.on(Socket.EVENT_CONNECT, args1 -> {
            System.out.println("连接成功");
            // 发送会话创建请求(需符合TradingView的消息格式)
            JSONObject sessionMsg = new JSONObject();
            sessionMsg.put("m", "quote_create_session");
            sessionMsg.put("p", new JSONObject[]{"qs_1"});
            socket.emit("message", sessionMsg);
        });

        // 监听消息接收事件
        socket.on("message", args1 -> {
            JSONObject msg = (JSONObject) args1[0];
            System.out.println("收到数据:" + msg.toString());
        });

        // 监听连接断开事件
        socket.on(Socket.EVENT_DISCONNECT, args1 -> System.out.println("连接断开"));

        // 启动连接
        socket.connect();
    }
}

3. 关键注意事项

  • TradingView的Socket.IO接口有特定的消息格式,比如会话创建、订阅指令等,需通过抓包或参考公开文档构造合法请求
  • 确保网络环境可访问TradingView服务器,必要时配置代理或处理SSL证书问题

内容的提问来源于stack exchange,提问作者ZacharyAlister

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 17:21:07