最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Netty網(wǎng)絡(luò)編程實戰(zhàn)之開發(fā)聊天室功能

 更新時間:2022年10月10日 10:25:53   作者:哪 吒  
這篇文章主要為大家詳細介紹了如何利用Netty實現(xiàn)聊天室功能,文中的示例代碼講解詳細,對我們學習Netty網(wǎng)絡(luò)編程有一定幫助,需要的可以參考一下

Netty網(wǎng)絡(luò)編程實戰(zhàn)1,搭建第一個Netty服務(wù)器中,使用curl作為客戶端訪問,下面將通過Netty實現(xiàn)客戶端,客戶端代碼依然采用Netty老套路 主程序類+自定義初始化器+自定義處理器三部分組成。

一、服務(wù)端

1、主程序類

package com.guor.demo.netty.chat;

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 MyNettyServerTest {
    public static void main(String[] args) throws InterruptedException {
        /**
         * EventLoopGroup:事件循環(huán)組,是一個線程池,也是一個死循環(huán),用于不斷地接收用戶請求;
         * serverGroup:用戶監(jiān)聽及建立連接,并把每一個連接抽象為一個channel,最后再將連接交給clientGroup處理;
         * clientGroup:真正的處理連接
         */
        EventLoopGroup serverGroup = new NioEventLoopGroup();
        EventLoopGroup clientGroup = new NioEventLoopGroup();
        try {
            // 服務(wù)端啟動時的初始化操作
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            // 1、將serverGroup和clientGroup注冊到服務(wù)端的Channel上;
            // 2、注冊一個服務(wù)端的初始化器MyNettyServerInitializer;
            // 3、該初始化器中的initChannel()方法會在連接被注冊到Channel后立刻執(zhí)行;
            // 5、最后將端口號綁定到8080;
            ChannelFuture channelFuture = serverBootstrap.group(serverGroup, clientGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new MyNettyServerInitializer()).bind(8080).sync();
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            System.out.println(e);
        }finally {
            serverGroup.shutdownGracefully();
            clientGroup.shutdownGracefully();
        }
    }
}

2、自定義初始化器

package com.guor.demo.netty.chat;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;

/**
 * 自定義初始化器
 */
public class MyNettyServerInitializer extends ChannelInitializer<SocketChannel> {

    // 連接被注冊到Channel后,立刻執(zhí)行此方法
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        /**
         * LengthFieldBasedFrameDecoder用于解析帶固定長度的數(shù)據(jù)報。
         * TCP發(fā)送的數(shù)據(jù)規(guī)則:可以將數(shù)據(jù)進行拆分或合并,因此對端接收到的數(shù)據(jù)報可能不是初始發(fā)送時的格式;
         * 一般的做法是在包頭設(shè)置length長度,指明數(shù)據(jù)包的長度,再由接受方根據(jù)length拼接或剪裁收到的數(shù)據(jù),從而形成完整的數(shù)據(jù)包
         */
        pipeline.addLast("LengthFieldBasedFrameDecoder",new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,8,0,8));
        // 將上條語句的length加入傳遞的數(shù)據(jù)中心
        pipeline.addLast("LengthFieldPrepender",new LengthFieldPrepender(8));
        // 傳遞字符串的編碼解碼器
        pipeline.addLast("StringDecoder",new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast("StringEecoder",new StringEncoder(CharsetUtil.UTF_8));
        // 增加自定義處理器MyNettyServerHandler,用于實際處理請求,并給出響應(yīng)
        pipeline.addLast("MyNettyServerHandler",new MyNettyServerHandler());
    }
}

3、自定義處理器

package com.guor.demo.netty.chat;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.util.Scanner;

/**
 * 自定義處理器
 * Inbound代表"進入"的請求
 */
public class MyNettyServerHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String receiveMsg) throws Exception {
        // 通過ctx獲取客戶端的IP和端口號,并打印出客戶端發(fā)來的消息
        System.out.println("服務(wù)端接收的請求來自:"+ctx.channel().remoteAddress()+",消息內(nèi)容:"+receiveMsg);

        System.out.println("請向客戶端發(fā)送一條消息:");
        String sendMsg = new Scanner(System.in).nextLine();
        ctx.channel().writeAndFlush(sendMsg);
    }
}

二、客戶端

1、主程序類

package com.guor.demo.netty.chat;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * 主程序類
 */
public class MyNettyClientTest {
    public static void main(String[] args) {
        /**
         * 服務(wù)端有兩個EventLoopGroup,serverGroup用于獲取連接并將連接分發(fā)給clientGroup,clientGroup負責處理連接;
         * 對于客戶端而言,客戶端僅僅需要連接服務(wù)端即可
         */
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        try {
            // 客戶端啟動時的初始化操作
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new MyNettyClientInitializer());
            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8080).sync();
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            System.out.println(e);
        }finally {
            eventLoopGroup.shutdownGracefully();
        }
    }
}

2、自定義初始化器

package com.guor.demo.netty.chat;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;

/**
 * 自定義初始化器
 */
public class MyNettyClientInitializer extends ChannelInitializer<SocketChannel> {

    // 連接被注冊后,立即執(zhí)行此方法
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        /**
         * LengthFieldBasedFrameDecoder用于解析帶固定長度的數(shù)據(jù)報。
         * TCP發(fā)送的數(shù)據(jù)規(guī)則:可以將數(shù)據(jù)進行拆分或合并,因此對端接收到的數(shù)據(jù)報可能不是初始發(fā)送時的格式;
         * 一般的做法是在包頭設(shè)置length長度,指明數(shù)據(jù)包的長度,再由接受方根據(jù)length拼接或剪裁收到的數(shù)據(jù),從而形成完整的數(shù)據(jù)包
         */
        pipeline.addLast("LengthFieldBasedFrameDecoder",new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,8,0,8));
        // 將上條語句的length加入傳遞的數(shù)據(jù)中心
        pipeline.addLast("LengthFieldPrepender",new LengthFieldPrepender(8));
        // 傳遞字符串的編碼解碼器
        pipeline.addLast("StringDecoder",new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast("StringEecoder",new StringEncoder(CharsetUtil.UTF_8));
        // 增加自定義處理器MyNettyClientHandler
        pipeline.addLast("MyNettyClientHandler",new MyNettyClientHandler());
    }
}

3、自定義處理器

package com.guor.demo.netty.chat;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.util.Scanner;

/**
 * 自定義處理器
 */
public class MyNettyClientHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String receiveMsg) throws Exception {
        System.out.println("客戶端接收的請求來自:"+ctx.channel().remoteAddress()+",消息內(nèi)容:"+receiveMsg);

        System.out.println("請向服務(wù)端發(fā)送一條消息:");

        String sendMsg = new Scanner(System.in).nextLine();

        ctx.channel().writeAndFlush(sendMsg);
    }

    public void channelActive(ChannelHandlerContext ctx) throws Exception{
        ctx.writeAndFlush("第一條消息...");
    }
}

三、啟動服務(wù)端、客戶端

1、服務(wù)端:你好,我是服務(wù)端,哪吒編程

2、客戶端:我去,還真連上了,第一次使用Netty通話,真神奇

3、服務(wù)端:土包子

到此這篇關(guān)于Netty網(wǎng)絡(luò)編程實戰(zhàn)之開發(fā)聊天室功能的文章就介紹到這了,更多相關(guān)Netty聊天室內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java 使用POI合并兩個word文檔

    java 使用POI合并兩個word文檔

    這篇文章主要介紹了java 使用POI合并兩個word文檔的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • SpringBoot生成和操作PDF的代碼詳解

    SpringBoot生成和操作PDF的代碼詳解

    本文主要介紹了在SpringBoot項目下,通過代碼和操作步驟,詳細的介紹了如何操作PDF,希望可以幫助到準備通過JAVA操作PDF的你,項目框架用的SpringBoot,但在JAVA中代碼都是通用的,需要的朋友可以參考下
    2025-01-01
  • Java實現(xiàn)文件的歸檔和解檔

    Java實現(xiàn)文件的歸檔和解檔

    這篇文章主要為大家詳細介紹了Java實現(xiàn)文件的歸檔和解檔,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • Java數(shù)組判斷是否越界的示例代碼

    Java數(shù)組判斷是否越界的示例代碼

    在Java編程中,避免數(shù)組越界是十分重要的,本文介紹了兩種常見的判斷數(shù)組是否越界的方法:一是通過數(shù)組的length屬性來判斷索引是否合法;二是通過捕獲ArrayIndexOutOfBoundsException異常來處理越界問題,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • 淺談在Java中JSON的多種使用方式

    淺談在Java中JSON的多種使用方式

    這篇文章主要介紹了淺談在Java中JSON的多種使用方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • Java使用JSqlParser解析SQL語句應(yīng)用場景

    Java使用JSqlParser解析SQL語句應(yīng)用場景

    JSqlParser是一個功能全面的Java庫,用于解析SQL語句,支持多種SQL方言,它可以輕松集成到Java項目中,并提供靈活的操作方式,本文介紹Java使用JSqlParser解析SQL語句總結(jié),感興趣的朋友一起看看吧
    2024-09-09
  • Java中ArrayList在foreach里remove的問題詳析

    Java中ArrayList在foreach里remove的問題詳析

    這篇文章主要給大家介紹了關(guān)于Java中ArrayList在foreach里remove問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起看看吧
    2018-09-09
  • 基于RecyclerChart的KLine繪制詳解

    基于RecyclerChart的KLine繪制詳解

    這篇文章主要為大家詳細介紹了基于RecyclerChart實現(xiàn)KLine繪制的相關(guān)資料,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-03-03
  • MyBatis實現(xiàn)表連接查詢寫法(三種對應(yīng)關(guān)系)的方法總結(jié)

    MyBatis實現(xiàn)表連接查詢寫法(三種對應(yīng)關(guān)系)的方法總結(jié)

    這篇文章主要介紹了MyBatis實現(xiàn)表連接查詢寫法(一對一關(guān)系、一對多關(guān)系、多對多關(guān)系)的方法,文中的示例代碼講解詳細,感興趣的可以了解一下
    2023-01-01
  • Java實現(xiàn)WORD和PDF互相轉(zhuǎn)換以及數(shù)據(jù)填充示例

    Java實現(xiàn)WORD和PDF互相轉(zhuǎn)換以及數(shù)據(jù)填充示例

    本文介紹了如何使用Java實現(xiàn)WORD和PDF的互轉(zhuǎn)以及數(shù)據(jù)填充功能,通過導(dǎo)入Aspose庫并使用其工具類,可以輕松實現(xiàn)WORD和PDF模板的填充和轉(zhuǎn)換,需要的朋友可以參考下
    2025-02-02

最新評論

大悟县| 中方县| 读书| 金山区| 永顺县| 贡觉县| 叙永县| 鄂温| 墨江| 铜陵市| 航空| 大城县| 无为县| 银川市| 汉中市| 寿光市| 兴义市| 凌海市| 瓮安县| 祁东县| 佛坪县| 曲靖市| 滕州市| 徐闻县| 新乐市| 温宿县| 正宁县| 旺苍县| 南京市| 和顺县| 定州市| 永昌县| 凤冈县| 通道| 五家渠市| 娄烦县| 美姑县| 临汾市| 湖北省| 西畴县| 阿坝|