Netty+html聊天室入門

1)服務端

ChatServer.java

package chat;

import chat.handler.WSServerInitializer;
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 ChatServer {
    public static void main(String[] args) {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new WSServerInitializer());

            int port = 8088;
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
            System.out.println("聊天服務器啓動成功 port:" + port);
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

2)WSServerInitializer.java

package chat.handler;

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 WSServerInitializer extends ChannelInitializer<SocketChannel> {
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new ChunkedWriteHandler());
        pipeline.addLast(new HttpObjectAggregator(1024 * 64));
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));

        // 業務Handler
        pipeline.addLast(new ChatHandler());
    }
}

3)ChatHandler.java

package chat.handler;

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

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    // 存儲所有的客戶端
    private static ConcurrentHashMap<ChannelHandlerContext, ChannelHandlerContext> clientHashMap = new ConcurrentHashMap<>();

    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
        String content = textWebSocketFrame.text();
        for (ChannelHandlerContext key : clientHashMap.keySet()) {
            ChannelHandlerContext ctx = key;
            ctx.channel().writeAndFlush(new TextWebSocketFrame(LocalDateTime.now() + " " + channelHandlerContext.channel().remoteAddress() + "說: " + content));
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客戶端進來了:" + ctx.channel().remoteAddress());
        clientHashMap.put(ctx, ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客戶端斷開連接:" + ctx.channel().remoteAddress());
        clientHashMap.remove(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("客戶端異常:" + ctx.channel().remoteAddress());
        cause.printStackTrace();
        ctx.close();
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <!--設置包名和版本號-->
    <artifactId>NettyChatRoom</artifactId>
    <version>1.0</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <!--設置java版本-->
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <!--設置入口類-->
                    <archive>
                        <manifest>
                            <mainClass>chat.ChatServer</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>

                    <!--去掉打包後綴-->
                    <appendAssemblyId>false</appendAssemblyId>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id> <!-- this is used for inheritance merges -->
                        <phase>package</phase> <!-- bind to the packaging phase -->
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.32.Final</version>
        </dependency>
    </dependencies>
</project>

2)客戶端

ChatClient.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title></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: gainsboro;"></div>

<script type="application/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("連接建立成功...");
                };

                CHAT.socket.onclose = function () {
                    console.log("連接關閉...");
                };

                CHAT.socket.onerror = function () {

                };

                CHAT.socket.onmessage = function (e) {
                    console.log("接收到消息" + e.data);
                    var receiveMsg = document.getElementById("receiveMsg");
                    var html = receiveMsg.innerHTML;
                    receiveMsg.innerHTML = html + "</br>" + e.data;
                };
            } else {
                alert("瀏覽器不支持websocket協議...");
            }
        },

        /**
         * 發送消息
         */
        chat: function () {
            var msg = document.getElementById("msgContent");
            CHAT.socket.send(msg.value);
        }
    };

    CHAT.init();
</script>
</body>
</html>

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章