WebSocketClient.class
package chnsoft.beliefflight.net.websocket;
import java.net.URI;
import java.net.URISyntaxException;
import chnsoft.beliefflight.Logger.LogProcess;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import io.netty.util.CharsetUtil;
public class WebSocketClient
{
public static final String _Tag = WebSocketClient.class.getSimpleName();
private final URI uri;
private Channel channel;
public WebSocketClient(String url) throws URISyntaxException
{
this.uri = new URI(url);
LogProcess.GetInstance().info(_Tag, "ws地址:" + uri.getHost() + ",端口:" + uri.getPort() + ",详细地址:" + uri.getPath());
}
public void connect()
{
NioEventLoopGroup group = new NioEventLoopGroup();
WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders());
WebSocketClientHandler handler = new WebSocketClientHandler(handshaker);
try
{
// 添加管道 绑定端口 添加作用域等
Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>()
{
@Override
protected void initChannel(SocketChannel socketChannel)
{
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new HttpClientCodec());
pipeline.addLast(new HttpObjectAggregator(8192));
// pipeline.addLast(WebSocketClientCompressionHandler.INSTANCE); 因为接了这行代码导致接收不到服务端数据
pipeline.addLast(handler);
}
});
// 启动连接
channel = bootstrap.connect(uri.getHost(), uri.getPort()).sync().channel();
// 等待握手响应
handler.handshakeFuture().sync();
}
catch (Exception e)
{
LogProcess.GetInstance().error(_Tag, "创建连接失败:" + e.getMessage());
}
}
public void sendMessage(String message)
{
if (channel != null && channel.isActive())
{
channel.writeAndFlush(new TextWebSocketFrame(message));
}
}
public void close() throws InterruptedException
{
if (channel != null && channel.isActive())
{
channel.close().sync();
}
}
private class WebSocketClientHandler extends SimpleChannelInboundHandler<Object>
{
/**
* 连接处理器
*/
private final WebSocketClientHandshaker webSocketClientHandshaker;
/**
* netty提供的数据过程中的数据保证
*/
private ChannelPromise handshakeFuture;
public WebSocketClientHandler(WebSocketClientHandshaker webSocketClientHandshaker)
{
this.webSocketClientHandshaker = webSocketClientHandshaker;
}
public ChannelFuture handshakeFuture()
{
return handshakeFuture;
}
/**
* 当客户端主动链接服务端的链接后,调用此方法
* @param ctx ChannelHandlerContext
*/
@Override
public void channelActive(ChannelHandlerContext ctx)
{
webSocketClientHandshaker.handshake(ctx.channel());
}
/**
* ChannelHandler添加到实际上下文中准备处理事件,调用此方法
* @param ctx ChannelHandlerContext
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx)
{
handshakeFuture = ctx.newPromise();
}
/**
* 链接断开后,调用此方法
*
* @param ctx ChannelHandlerContext
*/
@Override
public void channelInactive(ChannelHandlerContext ctx)
{
LogProcess.GetInstance().info(_Tag, "websocket连接断开");
connect();
}
/**
* 接收消息,调用此方法
*/
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object msg)
{
// 处理接收到的WebSocketFrame
LogProcess.GetInstance().info(_Tag, "接收到UWB数据:" + msg);
//是否直接解析json数据?
if (!webSocketClientHandshaker.isHandshakeComplete())
{
try
{
//连接建立成功,握手完成
webSocketClientHandshaker.finishHandshake(channelHandlerContext.channel(), (FullHttpResponse) msg);
//连接完成
handshakeFuture.setSuccess();
LogProcess.GetInstance().info(_Tag, "websocket已经建立连接");
}
catch (WebSocketHandshakeException e)
{
LogProcess.GetInstance().info(_Tag, "websocket连接失败!");
handshakeFuture.setFailure(e);
}
return;
}
if (msg instanceof FullHttpResponse)
{
FullHttpResponse response = (FullHttpResponse) msg;
throw new IllegalStateException("Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content().toString(CharsetUtil.UTF_8) + ')');
}
this.handleWebSocketFrame(msg);
}
/**
* 处理http连接请求.<br>
* @param msg:
*/
private void handleHttpRequest(Object msg)
{
webSocketClientHandshaker.finishHandshake(channel, (FullHttpResponse) msg);
handshakeFuture.setSuccess();
}
/**
* 处理文本帧请求.<br>
* @param msg 消息
*/
private void handleWebSocketFrame(Object msg)
{
WebSocketFrame frame = (WebSocketFrame) msg;
if (frame instanceof TextWebSocketFrame)
{
TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
// ...自定义
String context = textFrame.text();
LogProcess.GetInstance().info(_Tag, "收到消息:" + context);
}
else if (frame instanceof CloseWebSocketFrame)
{
LogProcess.GetInstance().info(_Tag, "连接收到关闭帧");
channel.close();
}
}
}
}
调用方式:
webSocketClient = new WebSocketClient("ws://192.168.43.117:8181/cs/v1/data/realtime");
// webSocketClient = new WebSocketClient("ws://192.168.43.117:8080/");
WebSocketClient("ws://192.168.43.22:8181/cs/v1/data/realtime");
ThreadPoolUtils.execute(() -> {
try
{
webSocketClient.connect();
}
catch (Exception e)
{
LogProcess.GetInstance().error(_Tag, "创建websocket连接失败:" + e.getMessage());
}
});
本文参考:【netty客户端】通过netty实现封装websocket客户端_netty websocket客户端-CSDN博客