netty 入门

  先啰嗦两句,使用 netty 来搭建服务器程序,可以发现相比于传统的 nio 程序, netty 的代码更加简洁,开发难度更低,扩展性也很好,非常适合作为基础通信框架.

下面上代码:

Server

package time.server.impl;

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;

/**
 * TODO
 *
 * @description
 * @author mjorcen
 * @time 2015年5月25日 下午2:50:57
 */
public class NTimeServerImpl {

    public void bind(int port) {
        // 创建两个NioEventLoopGroup 实例,NioEventLoopGroup
        // 是一个线程组,它包含一组NIO线程,专门用于处理网络事件的处理,实际上他们就是Reactor 线程组
        // 这里创建两个的原因是一个用于服务端接收用户的链接,另一个用于进行SocketChannel的网络读写
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            // 创建一个 ServerBootstrap ,它是netty用于NIO服务端的辅助启动类,目的是降低服务端的开发复杂度.
            ServerBootstrap bootstrap = new ServerBootstrap();
            // 设定 服务端接收用户请求的线程组和用于进行SocketChannel网络读写的线程组
            bootstrap.group(bossGroup, workerGroup);
            // 设置创建的 channel 类型
            bootstrap.channel(NioServerSocketChannel.class);
            // 配置 NioServerSocketChannel 的 tcp 参数, BACKLOG 的大小
            bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
            // 绑定io处理类(childChannelHandler).他的作用类似于 reactor 模式中的 handler
            // 类,主要用于处理网络 I/O 事件,例如对记录日志,对消息进行解码等.
            bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new TimeServerHandler());
                }
            });
            // 绑定端口,随后调用它的同步阻塞方法 sync 等等绑定操作成功,完成之后 Netty 会返回一个 ChannelFuture
            // 它的功能类似于的 Future,主要用于异步操作的通知回调.
            ChannelFuture channelFuture = bootstrap.bind(port).sync();
            // 等待服务端监听端口关闭,调用 sync 方法进行阻塞,等待服务端链路关闭之后 main 函数才退出.
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 优雅的退出,释放线程池资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        NTimeServerImpl server = new NTimeServerImpl();
        server.bind(9091);
    }

}

Server Handler

package time.server.impl;

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

import java.util.Date;

import time.TimeConfig;

/**
 * TODO
 *
 * @description
 * @author ez
 * @time 2015年5月25日 下午3:06:09
 */
public class TimeServerHandler extends ChannelHandlerAdapter implements
        TimeConfig {

    /*
     * (non-Javadoc)
     *
     * @see io.netty.channel.ChannelHandlerAdapter#channelRead(io.netty.channel.
     * ChannelHandlerContext, java.lang.Object)
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        byte[] req = new byte[buf.readableBytes()];
        buf.readBytes(req);
        String body = new String(req, "utf-8");
        System.out.println("The time server receive order : " + body);
        String currentTime = QUERY.equalsIgnoreCase(body) ? new Date()
                .toString() : "BAD ORDER";
        System.out.println("currentTime : " + currentTime);
        ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes("utf-8"));
        ctx.writeAndFlush(resp);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        // 当出现异常时,释放资源.
        ctx.close();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

}

client

package time.client.impl;

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

/**
 * TODO
 *
 * @description
 * @author ez
 * @time 2015年5月25日 下午3:17:29
 */
public class NTimeClient {

    public void connect(int port, String host) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {

            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.option(ChannelOption.TCP_NODELAY, true);
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {

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

            // 发起异步链接操作
            ChannelFuture future = bootstrap.connect(host, port).sync();

            // 等待客户端链路关闭
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        NTimeClient client = new NTimeClient();
        client.connect(9091, "localhost");
    }
}

client handler

package time.client.impl;

import java.io.UnsupportedEncodingException;

import time.TimeConfig;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

/**
 * TODO
 *
 * @description
 * @author ez
 * @time 2015年5月25日 下午3:21:26
 */
public class TimeClientHandler extends ChannelHandlerAdapter implements
        TimeConfig {
    private final ByteBuf message;

    public TimeClientHandler() throws UnsupportedEncodingException {
        byte[] bs = QUERY.getBytes("utf-8");
        message = Unpooled.buffer(bs.length);
        message.writeBytes(bs);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        cause.printStackTrace();
        // 异常时,调用这个方法
        ctx.close();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //  当客户端和服务器 TCP 链路建立成功之后,调用这个方法.
        ctx.writeAndFlush(message);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        // 当服务端返回应答消息时,调用这个方法.
        ByteBuf buf = (ByteBuf) msg;
        byte[] bs = new byte[buf.readableBytes()];
        buf.readBytes(bs);
        System.out.println(new String(bs, "utf-8"));
    }

}
时间: 2024-10-10 23:50:07

netty 入门的相关文章

Netty入门二:开发第一个Netty应用程序

    既然是入门,那我们就在这里写一个简单的Demo,客户端发送一个字符串到服务器端,服务器端接收字符串后再发送回客户端. 2.1.配置开发环境 1.安装JDK 2.去官网下载jar包 (或者通过pom构建) 2.2.认识下Netty的Client和Server 一个Netty应用模型,如下图所示,但需要明白一点的是,我们写的Server会自动处理多客户端请求,理论上讲,处理并发的能力决定于我们的系统配置及JDK的极限. Client连接到Server端 建立链接发送/接收数据 Server端

Netty入门之客户端与服务端通信(二)

Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码吧. 二.客户端与服务端的通信 2.1 服务端启动程序 public class MyServer { public static void main(String[] args) throws InterruptedException { EventLoopGroup bossGroup = ne

netty入门实例

TimeServer.java package netty.timeserver.server; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGro

Netty入门之WebSocket初体验

说一说IO通信 BIO通信: BIO即同步阻塞模式一请求一应答的通信模型,该模型最大的问题就是缺乏弹性伸缩能力,当客户端并发访问量增加后,服务端的线程个数和客户端并发访问数呈1:1的正比关系,由于线程是JAVA虚拟机非常宝贵的系统资源,当线程数膨胀之后,系统的性能将急剧下降,随着并发访问量的继续增大,系统会发生线程堆栈溢出.创建新线程失败等问题,并最终导致进程宕机或者僵死,不能对外提供服务. BIO的服务端通信模型: 采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责监听客户端

JAVA通信系列三:Netty入门总结

一.Netty学习资料 书籍<Netty In Action中文版> 对于Netty的十一个疑问http://news.cnblogs.com/n/205413/ 深入浅出Nettyhttp://wenku.baidu.com/view/7765bc2db4daa58da0114a4c.html Netty了解与小试 http://www.cnblogs.com/xd502djj/archive/2012/06/25/2561318.html Netty系列之Netty高性能之道[精彩]htt

netty 入门(一)

netty Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序.更确切的讲是一个组件,没有那么复杂. 例子 一  Discard服务器端 我们先写一个简单的服务端和客户端作为入门,接下来我们在深入介绍里面的内容 :(基于netty4 ) package io.netty.example.discard; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandl

(入门篇 NettyNIO开发指南)第三章-Netty入门应用

作为Netty的第一个应用程序,我们依然以第2章的时间服务器为例进行开发,通过Netty版本的时间服务报的开发,让初学者尽快学到如何搭建Netty开发环境和!运行Netty应用程序. 如果你已经熟悉Netty    的基础应用,可以跳过本章,继续后面知识的学习.本章主要内容包括:.Netty开发环境的搭建.服务端程序TimeServer开发.客户端程序TimeClient开发时间服务器的运行和调试 3.1    Netty开发环境的搭建 首先假设你已经在本机安装了JDKI.7贯配置了JDK的环境

【Netty】NIO框架Netty入门

Netty介绍 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 也就是说,Netty 是一个基于NIO的客户.服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用.Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发. 官网地址:http://netty.io/ 使用场景 Nett

精通并发与Netty入门一:Netty理论知识介绍

Netty是目前无论是国内还是国外各大互联网公司必备的一个网络应用框架.Netty本身既然是网络框架,处理的基本都是与网络相关的这样的一些作用.由于Netty本身在设计上的一些非常巧妙的方式,是对于NIO的一个很好的实现.Netty在各种应用场景下都会得到很广泛的应用.无论是传统的基于http的这种短连接方式还是基于底层Socket的这样的访问方式.另外还支持H5中规范中新增加的一个特别重要的标准,就是关于长连接的websocket这样一种新的规范.Netty对于其提供了非常好的支撑.那么Net

Netty 入门示例

服务端代码示例 import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; public class TimeServer { public void bind(int port) throws Except