美文网首页
netty-websocket最简实例

netty-websocket最简实例

作者: 不知不怪 | 来源:发表于2023-01-31 14:17 被阅读0次

1.pom

<?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>com.gzz</groupId>
    <artifactId>Websocket-Netty</artifactId>
    <version>1.0</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-codec-http</artifactId>
            <version>4.1.87.Final</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.4.5</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.server

package com.gzz;

import java.util.Timer;
import java.util.TimerTask;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
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;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class NettyServer {
    public static void main(String[] args) throws Exception {
        SocketHandler socketHandler = new SocketHandler();

        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                socketHandler.send("Hello world!");
            }
        }, 3000, 3000); // 3秒后每3秒执行一次

        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(boss, worker);
        bootstrap.channel(NioServerSocketChannel.class);
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel channel) {
                ChannelPipeline pipeline = channel.pipeline();
                pipeline.addLast("http-codec", new HttpServerCodec());// 设置解码器
                pipeline.addLast("aggregator", new HttpObjectAggregator(65536));// 聚合器,使用websocket会用到
                pipeline.addLast("http-chunked", new ChunkedWriteHandler());// 用于大数据的分区传输
                pipeline.addLast("handler", socketHandler);// 自定义的业务handler
                pipeline.addLast(new WebSocketServerProtocolHandler("/websocket"));// 接入点
            }
        });
        Channel channel = bootstrap.bind(8081).sync().channel();
        log.info("webSocket服务器启动成功:" + channel);
        channel.closeFuture().sync();
    }
}
//1 netty直接websocket
//2 统一消息体
//3 统一接入点
//4 前端用一个共用连接 消息类型

3.SocketHandler

package com.gzz;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Sharable
public class SocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    private static final ConcurrentMap<String, Channel> session = new ConcurrentHashMap<>();
    private static final DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
        log.info("收到消息:" + msg.text());
        ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器时间:" + LocalDateTime.now().format(format) + msg.text()));
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        session.put(parseIp(ctx.channel().remoteAddress().toString()), ctx.channel());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        session.remove(parseIp(ctx.channel().remoteAddress().toString()));
    }

    /**
     * 指定客户端消息
     */
    public void send(String message, String ip) {
        session.get(ip).writeAndFlush(new TextWebSocketFrame("服务器时间:" + LocalDateTime.now().format(format) + message));
    }

    /**
     * 广播消息
     */
    public void send(String message) {
        session.values().forEach(ch -> ch.writeAndFlush(new TextWebSocketFrame("服务器时间:" + LocalDateTime.now().format(format) + message)));
    }

    private String parseIp(String ip) {
        return ip.indexOf("0:0:0:0:0:0:0:1") > 0 ? "127.0.0.1" : ip.replaceAll("(/)(.*)(:)(.*)", "$2");
    }
}

4.index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>直接用浏览器打开文件即可</title>
</head>
<body>
    <textarea rows="10" cols="50" id="sendMsg" >{"id":1,"name":"高振中","gender":"男"}</textarea>   
    <button onclick=send()>发送</button>
    <textarea rows="10" cols="70" id="responseText" ></textarea>
    <button onclick="responseText.value=''">清空</button>
</body>
<script type="text/javascript">
    var socket;
    if (!window.WebSocket) {
        window.WebSocket = window.MozWebSocket;
    }
    if (window.WebSocket) {
        socket = new WebSocket("ws://localhost:8081/websocket");
        socket.onmessage = function(event) {
            responseText.value += event.data + "\r\n";
        };
        socket.onopen = function(event) {
            responseText.value = "打开WebSoket 服务正常,浏览器支持WebSoket!" + "\r\n";
        };
        socket.onclose = function(event) {
            responseText.value = "";
            responseText.value = "WebSocket 关闭" + "\r\n";
        };
    } else {
        alert("您的浏览器不支持WebSocket协议!");
    }

    function send() {
        if (!window.WebSocket) {
            return;
        }
        if (socket.readyState == WebSocket.OPEN) {
            socket.send(sendMsg.value);
        } else {
            alert("WebSocket 连接没有建立成功!");
        }
    }
</script>
</html>

1675232322246.png

相关文章

网友评论

      本文标题:netty-websocket最简实例

      本文链接:https://www.haomeiwen.com/subject/alxbhdtx.html