国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Netty與WebSocket:輕松搞定消息推送

開發 前端
學過 Netty 的都知道,Netty 對 NIO 進行了很好的封裝,簡單的 API,龐大的開源社區。深受廣大程序員喜愛。基于此本文分享一下基礎的 netty 使用。實戰制作一個 Netty + websocket 的消息推送小栗子。

學過 Netty 的都知道,Netty 對 NIO 進行了很好的封裝,簡單的 API,龐大的開源社區。深受廣大程序員喜愛。基于此本文分享一下基礎的 netty 使用。實戰制作一個 Netty + websocket 的消息推送小栗子。

netty服務器

@Component
public class NettyServer {

    static final Logger log = LoggerFactory.getLogger(NettyServer.class);

    /**
     * 端口號
     */
    @Value("${webSocket.netty.port:8888}")
    int port;

    EventLoopGroup bossGroup;
    EventLoopGroup workGroup;

    @Autowired
    ProjectInitializer nettyInitializer;

    @PostConstruct
    public void start() throws InterruptedException {
        new Thread(() -> {
            bossGroup = new NioEventLoopGroup();
            workGroup = new NioEventLoopGroup();
            ServerBootstrap bootstrap = new ServerBootstrap();
            // bossGroup輔助客戶端的tcp連接請求, workGroup負責與客戶端之前的讀寫操作
            bootstrap.group(bossGroup, workGroup);
            // 設置NIO類型的channel
            bootstrap.channel(NioServerSocketChannel.class);
            // 設置監聽端口
            bootstrap.localAddress(new InetSocketAddress(port));
            // 設置管道
            bootstrap.childHandler(nettyInitializer);

            // 配置完成,開始綁定server,通過調用sync同步方法阻塞直到綁定成功
            ChannelFuture channelFuture = null;
            try {
                channelFuture = bootstrap.bind().sync();
                log.info("Server started and listen on:{}", channelFuture.channel().localAddress());
                // 對關閉通道進行監聽
                channelFuture.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

    /**
     * 釋放資源
     */
    @PreDestroy
    public void destroy() throws InterruptedException {
        if (bossGroup != null) {
            bossGroup.shutdownGracefully().sync();
        }
        if (workGroup != null) {
            workGroup.shutdownGracefully().sync();
        }
    }
}

Netty配置

管理全局Channel以及用戶對應的channel(推送消息)

public class NettyConfig {

    /**
     * 定義全局單利channel組 管理所有channel
     */
    private static volatile ChannelGroup channelGroup = null;

    /**
     * 存放請求ID與channel的對應關系
     */
    private static volatile ConcurrentHashMap<String, Channel> channelMap = null;

    /**
     * 定義兩把鎖
     */
    private static final Object lock1 = new Object();
    private static final Object lock2 = new Object();


    public static ChannelGroup getChannelGroup() {
        if (null == channelGroup) {
            synchronized (lock1) {
                if (null == channelGroup) {
                    channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
                }
            }
        }
        return channelGroup;
    }

    public static ConcurrentHashMap<String, Channel> getChannelMap() {
        if (null == channelMap) {
            synchronized (lock2) {
                if (null == channelMap) {
                    channelMap = new ConcurrentHashMap<>();
                }
            }
        }
        return channelMap;
    }

    public static Channel getChannel(String userId) {
        if (null == channelMap) {
            return getChannelMap().get(userId);
        }
        return channelMap.get(userId);
    }
}

管道配置

@Component
public class ProjectInitializer extends ChannelInitializer<SocketChannel> {

    /**
     * webSocket協議名
     */
    static final String WEBSOCKET_PROTOCOL = "WebSocket";

    /**
     * webSocket路徑
     */
    @Value("${webSocket.netty.path:/webSocket}")
    String webSocketPath;
    @Autowired
    WebSocketHandler webSocketHandler;

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        // 設置管道
        ChannelPipeline pipeline = socketChannel.pipeline();
        // 流水線管理通道中的處理程序(Handler),用來處理業務
        // webSocket協議本身是基于http協議的,所以這邊也要使用http編解碼器
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new ObjectEncoder());
        // 以塊的方式來寫的處理器
        pipeline.addLast(new ChunkedWriteHandler());
        pipeline.addLast(new HttpObjectAggregator(8192));
        pipeline.addLast(new WebSocketServerProtocolHandler(webSocketPath, WEBSOCKET_PROTOCOL, true, 65536 * 10));
        // 自定義的handler,處理業務邏輯
        pipeline.addLast(webSocketHandler);
    }
}

自定義handler

@Component
@ChannelHandler.Sharable
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    private static final Logger log = LoggerFactory.getLogger(NettyServer.class);

    /**
     * 一旦連接,第一個被執行
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        log.info("有新的客戶端鏈接:[{}]", ctx.channel().id().asLongText());
        // 添加到channelGroup 通道組
        NettyConfig.getChannelGroup().add(ctx.channel());
    }

    /**
     * 讀取數據
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        log.info("服務器收到消息:{}", msg.text());

        // 獲取用戶ID,關聯channel
        JSONObject jsonObject = JSONUtil.parseObj(msg.text());
        String uid = jsonObject.getStr("uid");
        NettyConfig.getChannelMap().put(uid, ctx.channel());

        // 將用戶ID作為自定義屬性加入到channel中,方便隨時channel中獲取用戶ID
        AttributeKey<String> key = AttributeKey.valueOf("userId");
        ctx.channel().attr(key).setIfAbsent(uid);

        // 回復消息
        ctx.channel().writeAndFlush(new TextWebSocketFrame("服務器收到消息啦"));
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        log.info("用戶下線了:{}", ctx.channel().id().asLongText());
        // 刪除通道
        NettyConfig.getChannelGroup().remove(ctx.channel());
        removeUserId(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info("異常:{}", cause.getMessage());
        // 刪除通道
        NettyConfig.getChannelGroup().remove(ctx.channel());
        removeUserId(ctx);
        ctx.close();
    }

    /**
     * 刪除用戶與channel的對應關系
     */
    private void removeUserId(ChannelHandlerContext ctx) {
        AttributeKey<String> key = AttributeKey.valueOf("userId");
        String userId = ctx.channel().attr(key).get();
        NettyConfig.getChannelMap().remove(userId);
    }
}

推送消息接口及實現類

public interface PushMsgService {

    /**
     * 推送給指定用戶
     */
    void pushMsgToOne(String userId, String msg);

    /**
     * 推送給所有用戶
     */
    void pushMsgToAll(String msg);

}
@Service
public class PushMsgServiceImpl implements PushMsgService {

    @Override
    public void pushMsgToOne(String userId, String msg) {
        Channel channel = NettyConfig.getChannel(userId);
        if (Objects.isNull(channel)) {
            throw new RuntimeException("未連接socket服務器");
        }

        channel.writeAndFlush(new TextWebSocketFrame(msg));
    }

    @Override
    public void pushMsgToAll(String msg) {
        NettyConfig.getChannelGroup().writeAndFlush(new TextWebSocketFrame(msg));
    }
}

測試

圖片圖片

鏈接服務器

圖片圖片

發送消息

圖片圖片

調用接口,往前端推送消息!

圖片圖片


圖片圖片

OK!

一個簡單的 netty 小栗子就完成了。


責任編輯:武曉燕 來源: 一安未來
相關推薦

2021-02-05 07:28:11

SpringbootNettyWebsocke

2024-09-12 14:50:08

2025-02-07 08:39:32

Shell部署測試

2023-07-26 07:28:55

WebSocket服務器方案

2024-09-02 09:31:19

2021-03-26 08:16:32

SpringbootWebsocket前端

2018-04-20 09:36:23

NettyWebSocket京東

2022-10-26 09:27:59

Python編程迭代器協議

2022-09-16 08:04:25

阿里云權限網絡

2009-12-11 15:37:58

Linux日志處理

2017-05-11 15:01:43

Androidweb布局

2024-10-11 11:32:22

Spring6RSocket服務

2009-10-23 17:51:51

Oracle用戶密碼

2010-09-17 14:04:14

JVM內存設置

2020-05-11 10:59:02

PythonWord工具

2024-08-09 08:52:26

2010-06-04 09:08:56

2009-11-12 10:53:57

ADO.NET連接My

2009-09-13 20:28:38

Linq插入數據

2010-07-27 14:25:02

linux文件編碼
點贊
收藏

51CTO技術棧公眾號

y4480在线8影院| 无码小电影在线观看网站免费| 免费一级欧美片在线观看| 欧美多人乱p欧美4p久久| 国产调教视频在线观看| 精品福利樱桃av导航| 中文字幕av专区| 91免费视频观看| 2019日韩中文字幕mv| 国产在线不卡一区| 在线国产精品网| 日韩高清不卡一区二区| 久久亚洲国产精品日日av夜夜| 欧美成人首页| 91牛牛免费视频| 精品国产精品国产偷麻豆| 日韩av片永久免费网站| 欧美黑人做爰爽爽爽| 国模极品一区二区三区| 国产精品调教视频| 日韩女优人人人人射在线视频| 日韩欧美99| 一本一本久久| 久久久久一区二区| 蜜桃伊人久久| 午夜精品一区二区三区在线观看| 中文字幕第21页| 色涩成人影视在线播放| 一本色道久久综合亚洲精品不卡| 成人免费淫片视频软件| 天天久久综合| av一区二区三区在线观看| 欧美成人一品| 久久精品国产美女| 久久精品国产99久久6| 艳母动漫在线观看| 97国产一区二区| 国产原创精品在线| 午夜亚洲福利老司机| 大型av综合网站| 日本不卡免费高清视频| 日韩一区二区三区精品视频第3页| 一本色道久久88精品综合| 成人免费毛片播放| 亚洲色欲色欲www| 在线免费观看h| 欧美三电影在线| 日韩欧美精品一区二区三区| 操人视频在线观看欧美| 亚洲视频分类| 国产综合欧美在线看| 国产在线一区二区综合免费视频| www.日日操| 欧美天天综合色影久久精品| 中文字幕资源网在线观看| 国产午夜精品视频免费不卡69堂| 成人在线超碰| 成人免费观看a| 视频一区国产视频| 能在线观看的av| 五月婷婷欧美视频| 美女航空一级毛片在线播放| 欧美精品中文字幕一区| 888久久久| 青青在线免费观看| 激情久久av一区av二区av三区| 色综合久久悠悠| 色喇叭免费久久综合| 一区二区不卡在线观看| 国产精品素人视频| 羞羞的视频在线看| 欧美综合第一页| 男女性色大片免费观看一区二区| 成人亚洲在线观看| 精品国产亚洲在线| 女人av一区| 国产高清精品软男同| **性色生活片久久毛片| 欧美性猛片xxxxx免费中国| 欧美性做爰毛片| 精品中文字幕一区二区| 黄页在线观看视频| 中文字幕一区二区精品| 99精品视频免费全部在线| 18禁免费观看网站| 亚洲 欧美综合在线网络| 日韩电影免费观| 91在线视频九色| 久久久国产综合精品女国产盗摄| 欧美黄色激情| 国产精品成av人在线视午夜片 | 久久国产手机看片| 亚洲欧美在线高清| 日本久久免费| 欧美日韩免费观看一区| 欧美网站在线观看| 日韩成人一级| 99热成人精品热久久66| 亚洲韩国欧洲国产日产av| 欧美黄色精品| av超碰在线| 97在线视频免费| 2017欧美狠狠色| 少妇精品视频一区二区免费看| 女同一区二区| 色欧美日韩亚洲| 欧美亚洲国产一区| 亚洲人辣妹窥探嘘嘘| 一个人看的www久久| 久久国产精品露脸对白| 超碰在线网址| 国产麻豆乱码精品一区二区三区| 亚洲成va人在线观看| 日韩中文字幕在线不卡| 一本一道波多野结衣一区二区| 杨幂一区二区三区免费看视频| 国产乱子夫妻xx黑人xyx真爽| 亚洲天堂日韩电影| 狠狠色丁香久久婷婷综合_中 | 亚洲黄色免费电影| 一区二区三区欧洲区| 白白操在线视频| 亚洲精品v天堂中文字幕| 首页亚洲欧美制服丝腿| 国产最新在线| 蜜桃精品久久久久久久免费影院| 欧美色图一区二区三区| 亚洲午夜极品| av中文天堂在线| 国产欧美日韩综合一区在线观看| 日韩欧美精品网址| 中文字幕免费一区二区三区| 精品欧美不卡一区二区在线观看| 99理论电影网| 欧美高清视频一二三区| 日韩和的一区二区| 欧美极品影院| 99热在线这里只有精品| 欧美激情a在线| 一区二区欧美精品| 一精品久久久| 18在线观看的| 精品人妻大屁股白浆无码| 久久精品成人欧美大片| 97精品国产97久久久久久久久久久久| 99视频有精品高清视频| 中文字幕无码精品亚洲35| 欧美国产视频日韩| 一区二区三区美女视频| 欧美日韩亚洲一区在线观看| 污视频在线看网站| 国产一级爱c视频| 97视频在线观看播放| 欧美性猛交xxxx免费看| 国产日韩一区二区三区在线播放| 99热99re6国产在线播放| 超碰成人免费在线| 久久久国产午夜精品 | www.欧美精品一二三区| 亚洲va在线va天堂| 亚洲免费观看高清在线观看| 国产乱子伦视频一区二区三区 | 欧美精品videosex牲欧美| 国产成a人无v码亚洲福利| 国产精品一区免费在线| 免费看一级大黄情大片| 人九九综合九九宗合| 欧美性猛交xxxx| 奇米影视7777精品一区二区| 99精品视频在线免费播放 | 国产精品伦子伦免费视频| 欧美这里有精品| 久久精品国产99国产| 国产精品日本一区二区不卡视频 | 国产精品一二三区| 成午夜精品一区二区三区软件| 久草网在线视频| 丝袜足脚交91精品| 欧美日韩国产成人| 91精品1区2区| 成人性视频网站| 国产精品国产一区| 免费毛片b在线观看| 电影天堂久久| 先锋影音日韩| 日本一区二区三区四区视频| 日韩女优av电影| 亚洲视频在线观看三级| 久久激情中文| 老牛影视av一区二区在线观看| 欧美69xxx| 四虎黄色影院| 中文字幕中文字幕一区三区| 日韩免费av片在线观看| 精品一区二区三区电影| 色综合一个色综合| 国产日韩欧美麻豆| 久久婷婷av| 日韩大片在线观看| 国产成人a视频高清在线观看|