欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

Netty網(wǎng)絡(luò)編程實(shí)戰(zhàn)1,搭建第一個Netty服務(wù)器中,使用curl作為客戶端訪問,下面將通過Netty實(shí)現(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ù)進(jìn)行拆分或合并,因此對端接收到的數(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,用于實(shí)際處理請求,并給出響應(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代表"進(jìn)入"的請求
 */
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負(fù)責(zé)處理連接;
         * 對于客戶端而言,客戶端僅僅需要連接服務(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ù)進(jìn)行拆分或合并,因此對端接收到的數(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ò)編程實(shí)戰(zhàn)之開發(fā)聊天室功能的文章就介紹到這了,更多相關(guān)Netty聊天室內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java多線程同步工具類CyclicBarrier的使用

    Java多線程同步工具類CyclicBarrier的使用

    本文主要介紹了Java多線程同步工具類CyclicBarrier的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • spring Boot 應(yīng)用通過Docker 來實(shí)現(xiàn)構(gòu)建、運(yùn)行、發(fā)布流程

    spring Boot 應(yīng)用通過Docker 來實(shí)現(xiàn)構(gòu)建、運(yùn)行、發(fā)布流程

    這篇文章主要介紹了spring Boot 應(yīng)用通過Docker 來實(shí)現(xiàn)構(gòu)建、運(yùn)行、發(fā)布流程,圖文詳解,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-11-11
  • java多線程編程之管道通信詳解

    java多線程編程之管道通信詳解

    這篇文章主要為大家詳細(xì)介紹了java多線程編程之線程間的通信,探討使用管道進(jìn)行通信,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Mybatis獲取參數(shù)值和查詢功能的案例詳解

    Mybatis獲取參數(shù)值和查詢功能的案例詳解

    這篇文章主要介紹了Mybatis獲取參數(shù)值和查詢功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • 手?jǐn)]一個Spring?Boot?Starter并上傳到Maven中央倉庫

    手?jǐn)]一個Spring?Boot?Starter并上傳到Maven中央倉庫

    本文主要介紹了手?jǐn)]一個Spring?Boot?Starter并上傳到Maven中央倉庫,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Java中常見的XML解析方法與應(yīng)用詳解

    Java中常見的XML解析方法與應(yīng)用詳解

    XML(eXtensible Markup Language)是一種用于存儲和傳輸數(shù)據(jù)的標(biāo)記語言,被廣泛應(yīng)用于表示和交換獨(dú)立于應(yīng)用程序和硬件平臺的結(jié)構(gòu)化信息,下面我們就來看看它的常見解析方法有哪些吧
    2024-01-01
  • 超詳細(xì)的Spring Boot入門筆記(總結(jié))

    超詳細(xì)的Spring Boot入門筆記(總結(jié))

    本篇文章主要介紹了超詳細(xì)的Spring Boot入門筆記(總結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • 吊打Java面試官之Lambda表達(dá)式 Stream API

    吊打Java面試官之Lambda表達(dá)式 Stream API

    這篇文章主要介紹了吊打Java之jdk8的新特性包括Lambda表達(dá)式、函數(shù)式接口、Stream API全面刨析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • java 中用split分割字符串,最后的空格等不被拆分的方法

    java 中用split分割字符串,最后的空格等不被拆分的方法

    下面小編就為大家?guī)硪黄猨ava 中用split分割字符串,最后的空格等不被拆分的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • struts2獲取服務(wù)器臨時目錄的方法

    struts2獲取服務(wù)器臨時目錄的方法

    這篇文章主要為大家詳細(xì)介紹了struts2獲取服務(wù)器臨時目錄的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09

最新評論