springboot+netty+websocket收发消息

编程

1.创建spring boot的工程,在这里就不赘述怎么创建了

2.引入netty的依赖

        <dependency>

<groupId>io.netty</groupId>

<artifactId>netty-all</artifactId>

<version>4.1.6.Final</version>

</dependency>

3.编写websocket服务

import io.netty.bootstrap.ServerBootstrap;

import io.netty.channel.ChannelFuture;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.nio.NioServerSocketChannel;

import org.springframework.stereotype.Component;

@Component

public class WSServer {

private static class SingletonWSServer {

static final WSServer instance = new WSServer();

}

public static WSServer getInstance() {

return SingletonWSServer.instance;

}

private EventLoopGroup mainGroup;

private EventLoopGroup subGroup;

private ServerBootstrap server;

private ChannelFuture future;

public WSServer() {

mainGroup = new NioEventLoopGroup();

subGroup = new NioEventLoopGroup();

server = new ServerBootstrap();

server.group(mainGroup, subGroup)

.channel(NioServerSocketChannel.class)

.childHandler(new WSServerInitialize());

}

public void start() {

this.future = server.bind(8088);

System.err.println("netty websocket start finish.");

}

}

4.初始化websocket

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelPipeline;

import io.netty.channel.socket.SocketChannel;

import io.netty.handler.codec.http.HttpObjectAggregator;

import io.netty.handler.codec.http.HttpServerCodec;

import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;

import io.netty.handler.stream.ChunkedWriteHandler;

public class WSServerInitialize extends ChannelInitializer<SocketChannel> {

@Override

protected void initChannel(SocketChannel ch) throws Exception {

ChannelPipeline pipeline = ch.pipeline();

// websocket 基于http协议,所以要有http解码器

pipeline.addLast(new HttpServerCodec());

// 对写大数据流的支持

pipeline.addLast(new ChunkedWriteHandler());

// 对httpMessage进行聚合,聚合成FullHttpRequest或FullHttpResponse

// 几乎在netty中的编程都会使用到此handler

pipeline.addLast(new HttpObjectAggregator(1024 * 64));

/**

* websocket 服务器处理协议,用于指定给客户端访问的路由: /ws

* 本handler会帮你处理一些繁重而复杂的事情

* 会帮你处理握手动作:handshaking(ping、pong、close)ping + pong = 心跳

* 对于websocket来讲,都是通过frames进行传输的,不同的数据类型对应的frames也不同

*/

pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));

// 自定义的handler

pipeline.addLast(new ChatHandler());

}

}

5.编写接收信息处理handler

import io.netty.channel.Channel;

import io.netty.channel.ChannelHandlerContext;

import io.netty.channel.SimpleChannelInboundHandler;

import io.netty.channel.group.ChannelGroup;

import io.netty.channel.group.DefaultChannelGroup;

import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import io.netty.util.concurrent.GlobalEventExecutor;

import java.time.LocalDateTime;

public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

// 用于记录和管理所有的客户端的channel

private static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

@Override

protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame msg) throws Exception {

// 获取客户端传输过来的消息

String content = msg.text();

System.out.println("接收到数据:" + content);

for (Channel channel : clients) {

channel.writeAndFlush(new TextWebSocketFrame("服务端在[" + LocalDateTime.now() + "]

接收到消息,消息为:" + content));

}

}

/**

* 当客户端连接服务端之后(打开链接)

* 获取客户端的channel,并且放到channelGroup中去管理

* @param ctx

* @throws Exception

*/

@Override

public void handlerAdded(ChannelHandlerContext ctx) throws Exception {

clients.add(ctx.channel());

}

@Override

public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {

// 当触发handlerRemoved之后,ChannelGroup会自动移除对应客户端的channel

// clients.remove(ctx.channel());

System.out.println("客户端断开,channel对应的长ID为:" + ctx.channel().id().asLongText());

System.out.println("客户端断开,channel对应的短ID为:" + ctx.channel().id().asShortText());

}

}

6.监听spring boot工程的启动

import org.springframework.context.ApplicationListener;

import org.springframework.context.event.ContextRefreshedEvent;

import org.springframework.stereotype.Component;

@Component

public class NettyBooter implements ApplicationListener<ContextRefreshedEvent> {

@Override

public void onApplicationEvent(ContextRefreshedEvent event) {

if (event.getApplicationContext().getParent() == null) {

try {

WSServer.getInstance().start();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

7.启动项目,在页面上测试

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>hello</title>

</head>

<body>

<div>发送消息</div>

<input type="text" id="msgContent">

<input type="button" value="点我发送" onclick="CHAT.chat();">

<div>接收消息:</div>

<div id="receiveMsg" style="background-color: yellow;"></div>

<script type="text/javascript">

window.CHAT = {

socket: null,

init: function() {

if (window.WebSocket) {

CHAT.socket = new WebSocket("ws://127.0.0.1:8088/ws");

CHAT.socket.onopen = function() {

console.log("connect success...");

},

CHAT.socket.onclose = function() {

console.log("connect close...");

},

CHAT.socket.onerror = function() {

console.log("connect error...");

},

CHAT.socket.onmessage = function(e) {

console.log("receive msg: " + e.data);

var receiveMsg = document.getElementById("receiveMsg");

var html = receiveMsg.innerHTML;

receiveMsg.innerHTML = html + "<br />" + e.data;

}

} else {

alert("do not support websocket..");

}

},

chat: function() {

var msgContent = document.getElementById("msgContent");

CHAT.socket.send(msgContent.value);

}

}

CHAT.init();

</script>

</body>

</html>

以上是 springboot+netty+websocket收发消息 的全部内容, 来源链接: utcz.com/z/514821.html

回到顶部