使用RSocket Spring连接Binance WebSocket遇异常,能否直接连接?
问题分析与解决方案
首先直接给结论:你不能直接用RSocket连接Binance的WebSocket端点,这也是你遇到ClosedChannelException的核心原因,下面具体拆解:
为什么会出现这个异常?
Binance提供的WebSocket服务是基于标准WebSocket协议的,它遵循的是WebSocket的原生消息交互逻辑——你需要发送特定格式的JSON订阅指令来获取数据流;而RSocket是一套独立的应用层协议,有自己专属的帧结构、交互模型(请求-响应、请求-流等),Binance的WebSocket服务器根本不识别RSocket协议的帧和route这类RSocket特有的指令,所以连接建立后会直接关闭通道,抛出ClosedChannelException。
你的代码里用RSocketRequester.route("/bnbbtc@aggTrade")是RSocket的专属用法,但Binance的WS端点完全不认这个逻辑,它需要的是你发送符合规范的订阅消息,而不是RSocket的路由指令。
正确的解决方式:改用Spring WebFlux标准WebSocket客户端
你完全不需要搭建RSocket代理服务器,直接改用Spring WebFlux自带的标准WebSocket客户端就能正常连接Binance的WebSocket端点。下面是修改后的测试代码:
@SpringBootTest @Slf4j class BinanceWebSocketIntegrationTest { private WebSocketClient webSocketClient; @BeforeEach void setup() { webSocketClient = new ReactorNettyWebSocketClient(); } @Test void shouldRetrieveAggregatedTradePrices() { // 构建Binance要求的订阅消息格式 String subscribeMessage = """ { "method": "SUBSCRIBE", "params": ["bnbbtc@aggTrade"], "id": 1 } """; Flux<String> tradeStream = webSocketClient.execute( URI.create("wss://stream.binance.com:9443/ws"), session -> session.send(Mono.just(session.textMessage(subscribeMessage))) .thenMany(session.receive().map(WebSocketMessage::getPayloadAsText)) .take(1) .doOnError(e -> log.error("接收交易数据出错: {}", e.getMessage())) ); StepVerifier.create(tradeStream) .consumeNextWith(response -> { assertThat(response).isNotNull(); log.info("收到交易数据: {}", response); }) .verifyComplete(); } }
代码关键点说明
- 使用
ReactorNettyWebSocketClient:这是Spring WebFlux提供的符合标准WebSocket协议的客户端实现,能和Binance的WS端点正常交互 - 发送指定格式的订阅消息:按照Binance的要求发送JSON格式的订阅指令,替代原来RSocket的
route逻辑 - 原生WebSocket消息处理:通过
session.receive()直接获取Binance推送的数据流,完全遵循标准WebSocket的交互逻辑
内容的提问来源于stack exchange,提问作者Flavio Oliva
相关产品推荐
相关产品推荐

