netty--helloword程序

1、使用netty需要使用到下面的java包

netty-all-5.0.0.Alpha2.jar

我们来看下面具体的代码

1. 创建一个ServerBootstrap实例
2. 创建一个EventLoopGroup来处理各种事件,如处理链接请求,发送接收数据等。
3. 定义本地InetSocketAddress( port)好让Server绑定
4. 创建childHandler来处理每一个链接请求
5. 所有准备好之后调用ServerBootstrap.bind()方法绑定Server

package bhz.netty.test;

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

public class Server {

    public static void main(String[] args) throws Exception {
        //1 第一个线程组 是用于接收Client端连接的 ,第一个线程也叫boss线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //2 第二个线程组 是用于实际的业务处理操作的,第二个线程组也叫worker
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        
        //3 创建一个辅助类Bootstrap,就是对我们的Server进行一系列的配置
        ServerBootstrap b = new ServerBootstrap(); 
        //把俩个工作线程组加入到Bootstrap中进来
        b.group(bossGroup, workerGroup)
        //我要指定使用NioServerSocketChannel这种类型的通道,不同的协议这里通道配置不一样
         .channel(NioServerSocketChannel.class)
        //一定要使用 childHandler 去绑定具体的 事件处理器
         .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel sc) throws Exception {
                //通过channel的方法,把ServerHandler添加进去
                sc.pipeline().addLast(new ServerHandler());
            }
        });
        //还可以配置channel的缓冲区大小等

        //绑定指定的端口 进行监听,这里必须调用sync()是异步操作
        ChannelFuture f = b.bind(8765).sync(); 
        
        //Thread.sleep(1000000);
        //为了让服务器端程序一直运行,不会停止,等价于/Thread.sleep(1000000);
        f.channel().closeFuture().sync();
        
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
         
        
        
    }
    
}
package bhz.netty.test;

/*
*注意所以的包都必须是netty的
*/
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

public class ServerHandler  extends ChannelHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    
            //do something msg
            ByteBuf buf = (ByteBuf)msg;
            byte[] data = new byte[buf.readableBytes()];
            buf.readBytes(data);
            String request = new String(data, "utf-8");
            System.out.println("Server: " + request);
            //写给客户端
            String response = "我是反馈的信息";
            ctx.writeAndFlush(Unpooled.copiedBuffer("888".getBytes())).;
            //.addListener(ChannelFutureListener.CLOSE);
            

    }

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

}

客户端对应的代码:

package bhz.netty.test;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
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;

public class Client {

    public static void main(String[] args) throws Exception {
        //客户端不需要boss线程组,只需要worker线程组就可以
        EventLoopGroup workgroup = new NioEventLoopGroup();
        //服务器端对应的ServerBootstrap
        Bootstrap b = new Bootstrap();
        b.group(workgroup)
        //服务器端对应的是NioServerSocketChannel
        .channel(NioSocketChannel.class)
        //服务器端对应的是childhandle
        .handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel sc) throws Exception {
                sc.pipeline().addLast(new ClientHandler());
            }
        });
        
        //ChannelFuture异步非阻塞的通道
        ChannelFuture cf1 = b.connect("127.0.0.1", 8765).sync();
        
        //buf
        cf1.channel().writeAndFlush(Unpooled.copiedBuffer("777".getBytes()));
        
        cf1.channel().closeFuture().sync();
        workgroup.shutdownGracefully();
        
    }
}
package bhz.netty.test;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

public class ClientHandler extends ChannelHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            //do something msg
            ByteBuf buf = (ByteBuf)msg;
            byte[] data = new byte[buf.readableBytes()];
            buf.readBytes(data);
            String request = new String(data, "utf-8");
            System.out.println("Client: " + request);
            
            
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }

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

第二个需要注意的地方

客户端多次调用write函数发送数据,但是最后才调用flush,server端收到的数据如下,server端只会收到一次数据,数据如下

所以在编写程序代码的时候,最好使用writeAndFlush()

第三个需要注意的地方

服务端收到客户端发送的数据,需要把数据回复给客户端,这里可以添加一个监听,监听客户端是否收到了服务器发送的数据,监听到客户端收到数据之后,服务端会主动关闭客户端和服务器端建立的连接,客户端的连接就没有了,但是服务器一直还运行

上述代码还有一个更简单的书写形式

在服务端的ServerHandle代码中添加

 

注意上面的操作是放在服务端中,如果放在客户端中,客户端把数据发送给服务器之后,如果客户端就调用上面的函数,当监听到服务器收到了客户端的数据之后,客户端就主动把连接关闭掉了,就会导致服务器端回复给客户端的数据客户端无法获取到。

原文地址:https://www.cnblogs.com/kebibuluan/p/8435623.html