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
相关产品推荐
相关产品推荐

