本文介绍websocket客户端实现的一种方式
闲来无事:也撸了一个demo放在码云上,当然如果看不懂,也可以留言,不想写博客专门讲这个服务端,现在很多博客也讲了服务端怎么做,虽然很多讲得不全,实在需要搞懂这个服务端怎么写的也可以加qq:857113009(服务端实现,简单封装了一下发布订阅):https://gitee.com/hellobb/webflux
(沃特玛傻了,前面放了几个月,居然放在私有库了)
服务端请参考这三个地址:
https://www.cnblogs.com/limuma/p/9315517.html
http://www.codebelief.com/article/2019/05/webflux-analysis-on-websocket-request-processing/
https://cloud.tencent.com/developer/article/1480108
客户端demo使用main方法实现,实际项目中需要根据自己的修改
package com.ontrade.quotation;
import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.concurrent.CountDownLatch;
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.UnicastProcessor;
import reactor.netty.http.client.HttpClient;
import reactor.netty.tcp.TcpClient;
//因为是用main启动的,所以都是静态方法,实际项目需要修改
public class WebsocketTest {
//只是为了阻塞主线程,防止退出,所以,真正使用的时候需要去除相关的这个东西
static CountDownLatch countDownLatch = new CountDownLatch(1);
//自定义的发送器
static UnicastProcessor<String> directProcessor = UnicastProcessor.create();
public static void main(String[] args) {
websocket();
directProcessor.onNext("发送了一条数据");
directProcessor.onNext("{\"FID\":\"003\",\"SUB\":\"OFEX.BTCPERP.Depth\"}");
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void websocket() {
ReactorNettyWebSocketClient client = new ReactorNettyWebSocketClient(httpClient());
try {
client.execute(new URI("ws://10.17.145.23:9988"), session -> {
Mono<Void> input = session.receive().doOnNext(webSocketMessage -> {
System.out.println("收到消息:" + webSocketMessage.getPayloadAsText(Charset.forName("UTF-8")));
}).doOnError(throwable -> System.out.println("发生异常:" + throwable))
.doOnComplete(() -> System.out.println("结束")).then();
Mono<Void> output = directProcessor.map(message -> session
.textMessage(message))
.flatMap(webSocketMessage -> session.send(Mono.just(webSocketMessage))).then();
//output也可以这样写,与上面二选一
/* output= session.send(Flux.create(
tFluxSink -> {
directProcessor.doOnNext(msg -> {
tFluxSink.next(session.textMessage(msg));
}).doFinally((x) -> {
tFluxSink.complete();
}).subscribe();
}));*/
return Mono.zip(input, output).then()
.doFinally(
signalType -> {
System.out.println("连接结束了,不知道是发生的了异常,还是正常断开,如果要重连,可以在这儿想办法再次发起连接");
countDownLatch.countDown();
});
}).onTerminateDetach().doOnError(throwable -> System.out.println("发生异常:"+throwable))
.subscribe(aVoid -> System.out
.println("这个打印只是想告诉使用的人,reactor中所有的发布订阅最终操作为订阅操作(subcribe)"));
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
//实际项目中,这个对象可以用@Bean,然后注入
public static HttpClient httpClient() {
TcpClient tcpClient = TcpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000)
.doOnConnected(connection ->
connection.addHandlerLast(new ReadTimeoutHandler(100))
.addHandlerLast(new WriteTimeoutHandler(10)));
return HttpClient.from(tcpClient);
}
}