netty之websocket

此示例并未处理websocket的断线重连问题。
注意:
1. 在网络良好的情况下,服务端或客户端主动断开,对方会收到相应的断开事件
2. 由于网络问题造成连接断开,对方并不知晓连接已断开,需要使用心跳检测来解决

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 io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class WebsocketServer {

    public static void main(String[] args) {
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();

        ServerBootstrap serverBootstrap = new ServerBootstrap();

        serverBootstrap.group(boss, worker)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new WebsocketServerInitializer());

        try {
            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
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;

public class WebsocketServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        // 由于websocket是基于http协议的,所以需要添加http需要的handler
        pipeline.addLast(new HttpServerCodec());
        // Handler的泛型将变为 FullHttpRequest 或 FullHttpResponse
        // 将同一个请求或响应数据进行聚合
        pipeline.addLast(new HttpObjectAggregator(8096));
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
        pipeline.addLast(new WebsocketServerHandler());
    }
}
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.time.LocalDateTime;
// 由于此示例只接受文本数据,所以泛型使用TextWebSocketFrame
public class WebsocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        System.out.println("收到消息:" + msg.text());
        ctx.channel().writeAndFlush(new TextWebSocketFrame("时间:" + LocalDateTime.now()));
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerAdded:" + ctx.channel().id().asLongText());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerRemoved:" + ctx.channel().id().asLongText());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.channel().close();
    }
}

websocket客户端

由于html5天生支持websocket,所以我们使用支持html5的浏览器作为websocket的客户端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>websocket</title>
</head>
<body>
<form onsubmit="return false;">
    <h3>客户端输入:</h3>
    <textarea id="sendMessage" name="message" style="width:400px; height: 200px;"></textarea>
    <input type="button" value="发送数据" onclick="javascript: send(document.getElementById('sendMessage').value)">

    <h3>服务端输出:</h3>
    <textarea id="responseText" style="width: 400px;height: 300px;"></textarea>
    <input type="button" onclick="javascript: document.getElementById('responseText').value = ''" value="清空内容">
</form>

<script>
    var socket;
    if (window.WebSocket){
        socket = new WebSocket("ws://localhost:8899/ws");

        // 接收到服务端消息事件
        socket.onmessage = function (event) {
            var responseText = document.getElementById("responseText");
            responseText.value = responseText.value + "\r\n" + event.data;
        }

        // 链接建立事件
        socket.onopen = function (ev) {
            var responseText = document.getElementById("responseText");
            responseText.value = "链接建立";
        }

        // 链接关闭事件
        socket.onclose = function (ev) {
            var responseText = document.getElementById("responseText");
            responseText.value = responseText.value + "\r\n链接已断开";
        }
    }else{
        alert("不支持websocket");
    }

    function send(message) {
        console.log(message);
        if (!window.WebSocket){
            return;
        }
        if (socket.readyState == WebSocket.OPEN){
            socket.send(message);
        }else{
            alert("链接已断开");
        }
    }
</script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值