(一)第一个netty的demo

2021-02-19  本文已影响0人  guessguess

由于在公司闲的蛋疼,看到Nio比较diao,所以开始学习起来,先实现一个简单的demo。

使用maven进行项目管理,依赖如下

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.gee</groupId>
  <artifactId>my-netty</artifactId>
  <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.16.Final</version>
        </dependency>


        <!-- 时间工具类 start -->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.9</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- 指定maven编译的jdk的版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

工程目录如下


工程项目结构

那么动手来先构建服务端

config连接配置,配置如下

package config;

public class ConnectConfig {
    private static final String host = "127.0.0.1";
    private static final int port = 9527;
    private static final int SO_BACKLOG = 1024;
    public static int getPort() {
        return port;
    }
    public static String getHost() {
        return host;
    }
    public static int getSoBacklog() {
        return SO_BACKLOG;
    }
    
}

server

(一)服务的启动类

package server;

import config.ConnectConfig;
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;
import server.handler.TimeServerChannelHandler;

public class TimeServer {
    public static void main(String arg[]) {
        //启动服务类
        startServer();
    }

    private static void startServer() {
        //用于处理accept事件
        EventLoopGroup boss = new NioEventLoopGroup();
        //用于处理通道的读写事件
        EventLoopGroup work = new NioEventLoopGroup();

        ServerBootstrap sb = new ServerBootstrap();
        //主线程其实就是serverSocket,这里使用的是Nio,所以需要指定类型为NioServerSocketChannel
        //childHandler,其实自己定义如何处理,服务端这边的通道
        sb.group(boss, work).option(ChannelOption.SO_BACKLOG, ConnectConfig.getSoBacklog())
                .channel(NioServerSocketChannel.class).childHandler(new TimeServerChannelHandler());

        ChannelFuture cf = null;
        try {
            //服务端绑定端口,直到绑定成功,会一直阻塞
            cf = sb.bind(ConnectConfig.getPort()).sync();
            //服务端的主通道,直到等到关闭,会一直阻塞
            cf.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //将对应的监听线程关闭,避免线程没有杀死
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }
    }
}

(二)服务的对于子通道的处理器

package client.handler;

import client.handler.adapter.TimeClientChannelHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;

public class TimeClientHandler extends ChannelInitializer<SocketChannel>{

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline().addLast(new TimeClientChannelHandlerAdapter());
    }
}

(三)服务的对于子通道的处理器适配器

package client.handler.adapter;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class TimeClientChannelHandlerAdapter extends ChannelInboundHandlerAdapter{

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String req = "what time it is";
        ctx.writeAndFlush(Unpooled.copiedBuffer(req.getBytes()));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf req = (ByteBuf) msg;
        byte[] reqinfo = new byte[req.readableBytes()];
        req.readBytes(reqinfo);
        System.out.println("now is " + new String(reqinfo, "UTF-8"));
    }
}

那么动手来先构建客户端

(一)客户端的启动类

package client;

import client.handler.TimeClientHandler;
import config.ConnectConfig;
import io.netty.bootstrap.Bootstrap;
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.NioSocketChannel;

public class TimeClient {
    public static void main(String args[]) {
        connect();
    }
    
    private static void connect() {
        //用于客户端处通道的读写
        EventLoopGroup work = new NioEventLoopGroup();
        
        Bootstrap b = new Bootstrap();
        b.group(work).option(ChannelOption.TCP_NODELAY, true).channel(NioSocketChannel.class)
                .handler(new TimeClientHandler());
        ChannelFuture cf = null;
        try {
            //一直阻塞,直到连接上服务端
            cf = b.connect(ConnectConfig.getHost(), ConnectConfig.getPort()).sync();
            //一直阻塞,直到该通道关闭
            cf.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //避免线程没有杀死
            work.shutdownGracefully();
        }
    }
}

(二)客户端的对于通道的处理器

package client.handler;

import client.handler.adapter.TimeClientChannelHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;

public class TimeClientHandler extends ChannelInitializer<SocketChannel>{

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline().addLast(new TimeClientChannelHandlerAdapter());
    }
}

(三)客户端的对于通道的处理器适配器

package client.handler.adapter;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class TimeClientChannelHandlerAdapter extends ChannelInboundHandlerAdapter{

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String req = "what time it is";
        ctx.writeAndFlush(Unpooled.copiedBuffer(req.getBytes()));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf req = (ByteBuf) msg;
        byte[] reqinfo = new byte[req.readableBytes()];
        req.readBytes(reqinfo);
        System.out.println("now is " + new String(reqinfo, "UTF-8"));
    }
}

最后运行,结果如下

服务端收到来自客户端的请求:what time it is
客户端得到服务端的响应:now is 2021-02-18T10:41:30.068+08:00
服务端
客户端
上一篇下一篇

猜你喜欢

热点阅读