NettyServer群發(fā)消息

在netty中我們可以使用ChannelGroup方式進(jìn)行群發(fā)消息,ChannelGroup繼承Set接口
關(guān)鍵代碼

+初始化器

public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel channel) {
        // 基于換行符號
        channel.pipeline().addLast(new LineBasedFrameDecoder(1024));
        // 解碼轉(zhuǎn)String,注意調(diào)整自己的編碼格式GBK废士、UTF-8
        channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));
        // 解碼轉(zhuǎn)String伍玖,注意調(diào)整自己的編碼格式GBK券膀、UTF-8
        channel.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));
        // 在管道中添加我們自己的接收數(shù)據(jù)實(shí)現(xiàn)方法
        channel.pipeline().addLast(new MyServerHandler());
    }

}

  • handler類
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;

import java.text.SimpleDateFormat;
import java.util.Date;


public class MyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 當(dāng)客戶端主動(dòng)鏈接服務(wù)端的鏈接后钟鸵,這個(gè)通道就是活躍的了性昭。也就是客戶端與服務(wù)端建立了通信通道并且可以傳輸數(shù)據(jù)
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //當(dāng)有客戶端鏈接后渣蜗,添加到channelGroup通信組
        ChannelHandler.channelGroup.add(ctx.channel());
        //日志信息
        SocketChannel channel = (SocketChannel) ctx.channel();
        System.out.println("鏈接報(bào)告開始");
        System.out.println("鏈接報(bào)告信息:有一客戶端鏈接到本服務(wù)端");
        System.out.println("鏈接報(bào)告IP:" + channel.localAddress().getHostString());
        System.out.println("鏈接報(bào)告Port:" + channel.localAddress().getPort());
        System.out.println("鏈接報(bào)告完畢");
        //通知客戶端鏈接建立成功
        String str = "通知客戶端鏈接建立成功" + " " + new Date() + " " + channel.localAddress().getHostString() + "\r\n";
        ctx.writeAndFlush(str);
    }


    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        super.handlerAdded(ctx);
    }

    /**
     * 當(dāng)客戶端主動(dòng)斷開服務(wù)端的鏈接后屠尊,這個(gè)通道就是不活躍的。也就是說客戶端與服務(wù)端的關(guān)閉了通信通道并且不可以傳輸數(shù)據(jù)
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客戶端斷開鏈接" + ctx.channel().localAddress().toString());
        // 當(dāng)有客戶端退出后耕拷,從channelGroup中移除讼昆。
        ChannelHandler.channelGroup.remove(ctx.channel());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //接收msg消息{與上一章節(jié)相比,此處已經(jīng)不需要自己進(jìn)行解碼}
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg);
        //收到消息后骚烧,群發(fā)給客戶端
        String str = "服務(wù)端收到:" + new Date() + " " + msg + "\r\n";
        ChannelHandler.channelGroup.writeAndFlush(str);
    }

    /**
     * 抓住異常浸赫,當(dāng)發(fā)生異常的時(shí)候,可以做一些相應(yīng)的處理赃绊,比如打印日志既峡、關(guān)閉鏈接
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        System.out.println("異常信息:\r\n" + cause.getMessage());
    }

}

  • ChannelHandler
public class ChannelHandler {

    //用于存放用戶Channel信息,也可以建立map結(jié)構(gòu)模擬不同的消息群
    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

}
  • 服務(wù)端


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class NettyServer {

    public static void main(String[] args) {
        new NettyServer().bing(7397);
    }

    private void bing(int port) {
        //配置服務(wù)端NIO線程組
        EventLoopGroup parentGroup = new NioEventLoopGroup(); //NioEventLoopGroup extends MultithreadEventLoopGroup Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
        EventLoopGroup childGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(parentGroup, childGroup)
                    .channel(NioServerSocketChannel.class)    //非阻塞模式
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childHandler(new MyChannelInitializer());
            ChannelFuture f = b.bind(port).sync();
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            childGroup.shutdownGracefully();
            parentGroup.shutdownGracefully();
        }

    }

}

啟動(dòng)我們的服務(wù)端碧查,啟動(dòng)成功之后运敢,使用windows命令行連接服務(wù)端
telnet localhost 7397(服務(wù)端的端口號)。
我們新建了四個(gè)客戶端窗口


客戶端窗口
channelGroup

我們在一個(gè)連接上的客戶端發(fā)送消息忠售,可以看到四個(gè)客戶端都收到了消息


客戶端

我們可以區(qū)分不同channel頻道發(fā)送的消息传惠,

 @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //接收msg消息{與上一章節(jié)相比,此處已經(jīng)不需要自己進(jìn)行解碼}
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 接收到消息:" + msg);
        //收到消息后稻扬,群發(fā)給客戶端
        String str = "服務(wù)端收到:" + new Date() + " " + msg + "\r\n";
      //  ChannelHandler.channelGroup.writeAndFlush(str);


        Channel channel = ctx.channel();
        ChannelHandler.channelGroup.forEach(e -> {
            if (channel != e) {
                e.writeAndFlush(channel.remoteAddress() + "發(fā)送的消息:" + msg + "\n");
            } else {
                e.writeAndFlush("自己 :" + msg + "\n");
            }
        });
    }
發(fā)送消息

可以看到自己收到的消息會(huì)和其他頻道略有卻別涉枫。

參考
netty案例,netty4.1基礎(chǔ)入門篇六《NettyServer群發(fā)消息》

使用網(wǎng)狀實(shí)現(xiàn)多客戶端連接并且互相通信

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腐螟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子困后,更是在濱河造成了極大的恐慌乐纸,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摇予,死亡現(xiàn)場離奇詭異汽绢,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)侧戴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門宁昭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跌宛,“玉大人,你說我怎么就攤上這事积仗〗校” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵寂曹,是天一觀的道長哎迄。 經(jīng)常有香客問我,道長隆圆,這世上最難降的妖魔是什么漱挚? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮渺氧,結(jié)果婚禮上旨涝,老公的妹妹穿的比我還像新娘。我一直安慰自己侣背,他們只是感情好白华,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秃踩,像睡著了一般衬鱼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上憔杨,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天鸟赫,我揣著相機(jī)與錄音,去河邊找鬼消别。 笑死抛蚤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的寻狂。 我是一名探鬼主播岁经,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蛇券!你這毒婦竟也來了缀壤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤纠亚,失蹤者是張志新(化名)和其女友劉穎塘慕,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒂胞,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡图呢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛤织。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡赴叹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出指蚜,到底是詐尸還是另有隱情乞巧,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布姚炕,位于F島的核電站摊欠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏柱宦。R本人自食惡果不足惜些椒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掸刊。 院中可真熱鬧免糕,春花似錦、人聲如沸忧侧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚓炬。三九已至松逊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肯夏,已是汗流浹背经宏。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驯击,地道東北人烁兰。 一個(gè)月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像徊都,于是被迫代替她去往敵國和親沪斟。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容