Netty简单的服务器和客户端搭建(一)

本文主要是刚学netty,搭建一个简单的服务器和客户端的入门demo。参考书籍《Netty in action》

1:开发工具为Idea,使用maven多模块依赖配置。以nettyParent为父parent project,然后在该工程下创建client和server两个module。

项目目录结构和parent中的maven配置如下:

Netty简单的服务器和客户端搭建(一)_第1张图片

这个项目中有两个模块,Server与Client,它们的依赖库相同,互相之间没有依赖关系



    
        netty-parent
        netty
        1.0-SNAPSHOT
    
    4.0.0

    client

    jar
    client

    
        
            
                org.codehaus.mojo
                exec-maven-plugin
                
                    
                        run-client
                        
                            java
                        
                    
                
                
                    client.EchoClient
                    
                        ${echo-server.hostname}
                        ${echo-server.port}
                    
                
            
        
    

2.1:EchoClientHandler:客户端逻辑处理,其实就是处理返回到客户端的数据。

package client;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;

/**
 *客户端逻辑
 */
public class EchoClientHandler extends SimpleChannelInboundHandler {
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //当前通知Channel是活跃的时候,发送一条信息
        ctx.writeAndFlush(Unpooled.copiedBuffer("netty rocks!",CharsetUtil.UTF_8));
    }

    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
        //记录已接受消息的转储
        System.out.println("Client received :" +
            byteBuf.toString(CharsetUtil.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

2.2:EchoClient:客户端引导,启动客户端,发起连接。

package client;

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

import java.net.InetSocketAddress;

/**
 * 客户端引导
 */
public class EchoClient {
    private final String host;
    private final int port;

    public EchoClient(String host,int port){
        this.port = port;
        this.host = host;
    }

    public void start() throws Exception{
        EventLoopGroup group = new NioEventLoopGroup();
        try{
            //创建BootStrap
            Bootstrap b = new Bootstrap();
            b.group(group)  //指定EvenLoopGroup 以处理客户端事件;需要适用于Nio的实现
                    .channel(NioSocketChannel.class)
                    .remoteAddress(new InetSocketAddress(host,port))
                    .handler(new ChannelInitializer() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) {
                            socketChannel.pipeline().addLast(
                                    new EchoClientHandler()
                            );
                        }
                    });
            ChannelFuture f = b.connect().sync();
            f.channel().closeFuture().sync();
        }finally {
            group.shutdownGracefully().sync();
        }
    }

    public static void main(String[] args) throws Exception{
        if(args.length != 2){
            System.out.println("Usage: "+EchoClient.class.getSimpleName()+
            "");
        }
    }
}

2.3:client中的maven配置



    
        netty-parent
        netty
        1.0-SNAPSHOT
    
    4.0.0

    client

    jar
    client

    
        
            
                org.codehaus.mojo
                exec-maven-plugin
                
                    
                        run-client
                        
                            java
                        
                    
                
                
                    client.EchoClient
                    
                        ${echo-server.hostname}
                        ${echo-server.port}
                    
                
            
        
    

3.1:EchoServerHandler:服务端业务逻辑处理。

package server;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

//业务逻辑处理
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
    //每个信息入站都会调用
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf in = (ByteBuf) msg;
        //将消息记录到控制台
        System.out.println("server received:" + in.toString(CharsetUtil.UTF_8));
        ctx.write(in);  //将接受到的消息写给发送者

    }

    //通知处理器最后的channelread是当前批处理中的最后一条信息调用
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //将未决消息冲刷到远程节点,并关闭该Channel
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
                .addListener(ChannelFutureListener.CLOSE);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();  //打印异常栈追踪
        ctx.close(); //关闭该channel
    }
}

3.2:EchoServer:服务端引导,启动服务器,绑定到du端口进行监听。

package server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.net.InetSocketAddress;

/**
 * 引导服务器
 * 绑定到服务器,将在其上监听并接受传入连接请求的端口
 */
public class EchoServer {

    private final int port;
    public EchoServer(int port){
        this.port = port;
    }

    public static void main(String[] args) throws Exception{
        if(args.length != 1){
            System.err.println("Usage: "+ EchoServer.class.getSimpleName()+"");
            return;
        }
        int port = Integer.parseInt(args[0]);
        new EchoServer(port).start();//调用服务器的start方法
    }

    public void start() throws Exception{
        final EchoServerHandler serverHandler = new EchoServerHandler();
        //创建Even Loop Group
        //配置服务器的NIO线程组
        //两个Reactor 一个用于服务器接收客户端的连接  一个用于经行SocketChannel的网络读写
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
            //创建ServerBootStrap
            ServerBootstrap b = new ServerBootstrap();
            //指定所使用的NIO传输Channle
            b.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class)
                    .localAddress(new InetSocketAddress(port))
                    .childHandler(new ChannelInitializer() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) {
                            //如果EchoServerHandler被注为@Shareable的时候,则可以总是使用同样的实例
                            socketChannel.pipeline().addLast(serverHandler);
                        }
                    });
            //异步的绑定服务器,调用sync方法阻塞,直到绑定完成
            ChannelFuture f = b.bind().sync();
            //获取Channel的CloseFuture,并阻塞当前线程直到它完成
            f.channel().closeFuture().sync();
        }finally {
            //关闭EvenLoopGroup,释放所有资源
            bossGroup.shutdownGracefully().sync();
            workerGroup.shutdownGracefully().sync();
        }
    }


}

3.3:Server中的Maven配置。



    
        netty-parent
        netty
        1.0-SNAPSHOT
    
    4.0.0

    server

    jar
    server

    
        
            
                org.codehaus.mojo
                exec-maven-plugin
                
                    
                        run-server
                        
                            java
                        
                    
                
                
                    server.EchoServer
                    
                        ${echo-server.port}
                    
                
            
        
    

4.1:编译项目,首先要配置好Maven环境变量,进入nettyParent目录下

输入 mvn clean package命令对项目进行编译

Netty简单的服务器和客户端搭建(一)_第2张图片

4.2:然后进入server目录,输入mvn exec:java 启动服务器  (因为parent中的Maven配置好了,所以这样启动即可)。

 

4.3:同样进入client目录下,输入mvn exec:java 启动客户端。

这样一个简单的netty服务器和客户端就搭建好了,本文参考了《Netty In Action》,

[Netty 源码分析](https://blog.csdn.net/tryingpfq/article/details/104692919)

Demo的GitHUb地址

 

你可能感兴趣的:(Netty学习)