天天看點

netty4學習筆記5-netty作為WebSocket伺服器

需求:

編寫一個WebSocket伺服器,來完成讀取用戶端的請求,并完成相應

編寫步驟:

1. 編寫伺服器端的啟動程式

package com.baidu.netty.fouthExample;

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;

public class MyServer {
    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).childHandler(new MyServerInitializer());
            ChannelFuture future = bootstrap.bind(8899).sync();
            future.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}
           

2. 編寫伺服器端的初始化程式

package com.baidu.netty.fouthExample;

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.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.CharsetUtil;

public class MyServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new HttpServerCodec());
        /**以塊的形式寫*/
        pipeline.addLast(new ChunkedWriteHandler());
        /**将塊組裝成對象(比如該處用到的文本對象)*/
        pipeline.addLast(new HttpObjectAggregator(1024));
        /**添加對于websocket的支援,參數配置的是通路的路徑*/
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
        pipeline.addLast(new MyServerHandler());
    }
}
           

3. 編寫伺服器的處理程式

package com.baidu.netty.fouthExample;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

public class MyServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        System.out.println("【用戶端的消息】:" + msg.text());
        /**傳回的時候也必須要是TextWebSocketFrame對象而不能是普通的字元串*/
        TextWebSocketFrame content = new TextWebSocketFrame("你好用戶端");
        ctx.writeAndFlush(content);
    }

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

4. 編寫html5的socket請求程式

<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>websocket通路netty</title>
    <script>
        var socket;
        if(window.WebSocket)
        {
            //第一個ws是協定,第二個ws是我們在pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); 配置的
            socket = new WebSocket("ws://localhost:8899/ws");
            //當socket得到資料的時候調用,相當于channelRead0
            socket.onmessage = function(event)
            {
                document.getElementById("content").value = event.data;
            }
            socket.onopen = function (ev) {
                document.getElementById("content").value = "用戶端連上了伺服器";
            }
            socket.onclose = function (ev) {
                document.getElementById("content").value = "用戶端斷開伺服器";
            }
        }else
        {
            alert("目前浏覽器不支援websocket程式");
        }

        function sendMsg() {
            if(socket && socket.readyState == WebSocket.OPEN)
            {
                socket.send(document.getElementById("content").value);
            }
        }
    </script>
</head>
<body>
<input value="發送" type="button" οnclick="sendMsg()"><br>
<textarea id="content"></textarea>
</body>
</html>