Netty介绍:

Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能、高可靠性的网络服务器和客户端程序。

换句话说,Netty是一个NIO框架,使用它可以简单快速地开发网络应用程序,比如客户端和服务端的协议。Netty大大简化了网络程序的开发过程比如TCP和UDP的 Socket的开发。

“快速和简单”并不意味着应用程序会有难维护和性能低的问题,Netty是一个精心设计的框架,它从许多协议的实现中吸收了很多的经验比如FTP、SMTP、HTTP、许多二进制和基于文本的传统协议,Netty在不降低开发效率、性能、稳定性、灵活性情况下,成功地找到了解决方案。

有一些用户可能已经发现其他的一些网络框架也声称自己有同样的优势,所以你可能会问是Netty和它们的不同之处。答案就是Netty的哲学设计理念。Netty从第一天开始就为用户提供了用户体验最好的API以及实现设计。正是因为Netty的设计理念,才让我们得以轻松地阅读本指南并使用Netty。

接下来,我们看下Client端的代码实现:

 package ruizhan.hjf.netty;

 import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
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;
/**
* Netty客户端的程序
* @author huangjianfei
*/
public class Client {
/*IP地址*/
static final String HOST = System.getProperty("host", "127.0.0.1");
/*端口号*/
static final int PORT1 = Integer.parseInt(System.getProperty("port", "8765")); static final int PORT2 = Integer.parseInt(System.getProperty("port", "8764")); public static void main(String[] args) throws Exception {
EventLoopGroup workgroup = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();//客户端
b.group(workgroup)
.channel(NioSocketChannel.class)//客户端 -->NioSocketChannel
.option(ChannelOption.SO_KEEPALIVE, true)
.handler(new ChannelInitializer<SocketChannel>() {//handler
@Override
protected void initChannel(SocketChannel sc) throws Exception {
sc.pipeline().addLast(new ClientHandler());
}
});
//创建异步连接 可添加多个端口
ChannelFuture cf1 = b.connect(HOST, PORT1).sync();
ChannelFuture cf2 = b.connect(HOST, PORT2).sync(); //buf
//client向server端发送数据 Buffer形式
cf1.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty".getBytes()));
cf2.channel().writeAndFlush(Unpooled.copiedBuffer("hello world".getBytes())); cf1.channel().closeFuture().sync();
cf2.channel().closeFuture().sync(); workgroup.shutdownGracefully();
}
}

Servler端代码实现:

 package ruizhan.hjf.netty;

 import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
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;
/**
* Netty实现的服务端程序
* @author huangjianfei
*/
public class Server
{
/*端口号*/
static final int PORT1 = Integer.parseInt(System.getProperty("port", "8765")); static final int PORT2 = Integer.parseInt(System.getProperty("port", "8764")); public static void main(String[] args)
{
EventLoopGroup bossGroup = null;
EventLoopGroup workerGroup = null;
ServerBootstrap b = null;
try{
//1:第一个线程组是用于接收Client连接的
bossGroup = new NioEventLoopGroup(); //(1)
//2:第二个线程组是用于实际的业务处理操作的
workerGroup = new NioEventLoopGroup();
//3:创建一个启动NIO服务的辅助启动类ServerBootstrap 就是对我们的Server进行一系列的配置
b = new ServerBootstrap();//(2)
//4:绑定两个线程组
b.group(bossGroup, workerGroup)
//5:需要指定使用NioServerSocketChannel这种类型的通道
.channel(NioServerSocketChannel.class)//(3) 服务端 -->NioServerSocketChannel
//6:一定要使用childHandler 去绑定具体的事件处理器
.childHandler(new ChannelInitializer<SocketChannel>() //(4) childHandler
{
@Override
protected void initChannel(SocketChannel sc) throws Exception
{
//7:将自定义的serverHandler加入到管道中去(多个)
sc.pipeline().addLast(new ServerHandler());//handler中实现真正的业务逻辑
// sc.pipeline().addLast(new ServerHandler());
// sc.pipeline().addLast(new ServerHandler());
}
})
/**
* 服务器端TCP内核模块维护两个队列,我们称之为A,B吧
* 客户端向服务端connect的时候,会发送带有SYN标志的包(第一次握手)
* 服务端收到客户端发来的SYN时,向客户端发送SYN ACK确认(第二次握手)
* 此时TCP内核模块把客户端连接加入到A队列中,最后服务端收到客户端发来的ACK时(第三次握手)
* TCP内核模块把客户端连接从A队列移到B队列,连接成功,应用程序的accept会返回
* 也就是说accept从B队列中取出完成三次握手的连接
* A队列和B队列的长度之和是backLog,当A,B队列的长度之和大于backLog时,新连接将会被TCP内核拒绝
* 所以,如果backLog过小,可能会出现accept速度跟不上,A,B队列满了,导致新的客户端无法连接,
* 要注意的是,backLog对程序支持的连接数并无影响,backLog影响的只是还没有被accept取出的连接
*/
//8:设置TCP连接的缓冲区
.option(ChannelOption.SO_BACKLOG, 128)//(5)
// .option(ChannelOption.SO_SNDBUF, 32*1024) //设置发送缓冲大小
// .option(ChannelOption.SO_RCVBUF, 32*1024) //设置接收缓冲大小
//9:保持连接
.childOption(ChannelOption.SO_KEEPALIVE, true);//(6)
//10:绑定指定的端口 进行监听
//此处端口号先写死 也可以绑定多个端口
ChannelFuture cf2= b.bind(PORT1).sync(); // (7) ChannelFuture cf3= b.bind(PORT2).sync(); // (7) 绑定多个端口 //Thread.sleep(10000);
cf2.channel().closeFuture().sync(); //异步等待关闭
cf3.channel().closeFuture().sync(); //异步等待关闭 }catch(Exception e){
e.printStackTrace();
}finally{
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}

接下来,就是真正去实现数据传输的业务逻辑层代码的实现,在这里也就是ClientHanlder和ServlerHandler:

 package ruizhan.hjf.netty;

 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; /**
* 客户端业务处理类
* (编写主要的业务逻辑)
* @author huangjianfei
*/
public class ClientHandler extends ChannelHandlerAdapter
{
// ByteBuf是一个引用计数对象,这个对象必须显示地调用release()方法来释放。
// 请记住处理器的职责是释放所有传递到处理器的引用计数对象。
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
{
try{
//do something
//接收服务端发来的数据 ByteBuf
ByteBuf buf = (ByteBuf)msg;
//创建一个和buf一样长度的字节空数组
byte[] data = new byte[buf.readableBytes()];
//将buf中的数据读取到data数组中
buf.readBytes(data);
//将data数组惊醒包装 以String格式输出
String response = new String(data,"utf-8");
System.out.println("client :"+response); //以上代码是接收服务端发来的反馈数据// ctx.close();
}finally{
// Discard the received data silently.
ReferenceCountUtil.release(msg);
}
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
{
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
}
}
 package ruizhan.hjf.netty;

 import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil; /**
* 服务端业务处理类
* (编写主要的业务逻辑)
* @author huangjianfei
*/
public class ServerHandler extends ChannelHandlerAdapter
{ /**
* 每当从客户端收到新的数据时,这个方法会在收到消息时被调用
* ByteBuf是一个引用计数对象,这个对象必须显示地调用release()方法来释放。
* 请记住处理器的职责是释放所有传递到处理器的引用计数对象。
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
{
try{
//do something
//接收客户端发送的数据 ByteBuf
ByteBuf buf = (ByteBuf)msg;
//创建一个和buf长度一样的空字节数组
byte[] data = new byte[buf.readableBytes()];
//将buf中的数据读取到data数组中
buf.readBytes(data);
//将data数据包装成string输出
String request = new String(data,"utf-8");
System.out.println("server :"+request); //以上代码是接收客户端信息// //server端向client发送反馈数据
//如果是绑定了多个端口 那么都会进行发送
ctx.writeAndFlush(Unpooled.copiedBuffer("888".getBytes()))
.addListener(ChannelFutureListener.CLOSE);//添加监听 当服务端向客户端发送完数据后,关闭connect连接
/**
* ChannelFutureListener,当一个写请求完成时通知并且关闭Channel
* 加上监听 意味着服务端回送数据到客户端时 连接关闭(短连接)
* 不加监听 意味着客户端与服务端一直保持连接状态(长连接)
*/ ctx.close();
}finally{
// Discard the received data silently.
ReferenceCountUtil.release(msg);
}
} /**
* exceptionCaught()事件处理方法是当出现Throwable对象才会被调用
* 即当Netty由于IO错误或者处理器在处理事件时抛出的异常时
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
{
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
} }

以上是Netty的基础入门实现,详见并发编程网,http://ifeve.com/netty5-user-guide/

关于Netty的入门使用的更多相关文章

  1. Netty快速入门(08)ByteBuf组件介绍

    前面的内容对netty进行了介绍,写了一个入门例子.作为一个netty的使用者,我们关注更多的还是业务代码.也就是netty中这两种组件: ChannelHandler和ChannelPipeline ...

  2. Netty快速入门(09)channel组件介绍

    书接上回,继续介绍组件. ChannelHandler组件介绍 ChannelHandler组件包含了业务处理核心逻辑,是由用户自定义的内容,开发人员百分之九十的代码都是ChannelHandler. ...

  3. netty的入门

    netty是什么? netty是一个基于NIO的通信框架,对于传统计算机,系统的瓶颈一直在输入输出设备上,计算速度超过IO速度,所以对于i o的性能提高异常重要. 什么是NIO? 非阻塞IO,N表示n ...

  4. 1、Netty 实战入门详解

    一.Netty 简介 Netty 是基于 Java NIO 的异步事件驱动的网络应用框架,使用 Netty 可以快速开发网络应用,Netty 提供了高层次的抽象来简化 TCP 和 UDP 服务器的编程 ...

  5. Netty从入门到精通到放弃

    有时间想记录一下关于Netty的知识. 第一课:传统IO的特点. package com.example.aimei.controller; import java.io.InputStream; i ...

  6. Netty框架入门

    一.概述     Netty是由JBOSS提供的一个java开源框架.     Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序.   二. ...

  7. 网络应用框架Netty快速入门

    一 初遇Netty Netty是什么? Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.可扩展协议的服务器和客户端 ...

  8. <Netty>(入门篇)TIP黏包/拆包问题原因及换行的初步解决之道

    熟悉TCP编程的读者可能都知道,无论是服务端还是客户端,当我们读取或者发送消息的时候,都需要考虑TCP底层的粘包/拆包机制.木章开始我们先简单介绍TCP粘包/拆包的基础知识,然后模拟一个没有考虑TCP ...

  9. Netty实战入门详解——让你彻底记住什么是Netty(看不懂你来找我)

    一.Netty 简介 Netty 是基于 Java NIO 的异步事件驱动的网络应用框架,使用 Netty 可以快速开发网络应用,Netty 提供了高层次的抽象来简化 TCP 和 UDP 服务器的编程 ...

随机推荐

  1. jquery获取选中的文本和值

    jquery获取选中的文本和值 1.说明 (1)获取select下拉框选中的索引       $("#selection").get(0).selectedIndex; (2)获取 ...

  2. HTML5中的输入框

    HTML5中的输入框 1.双引号 <input type="text"/> 2.单引号 <input type='text'/> 3.无引号 <inp ...

  3. Openstack_后端存储平台Ceph

    框架图 介绍 一种为优秀的性能.可靠性和可扩展性而设计的统一的.分布式文件系统 特点 CRUSH算法 Crush算法是ceph的两大创新之一,简单来说,ceph摒弃了传统的集中式存储元数据寻址的方案, ...

  4. 三十天学不会TCP,UDP/IP网络编程 - 绅士的开始

    经过了过年的忙碌和年初的懈怠一切的日子,我又开始重新更新了~这是最新的一篇~完整版可以去gitbook(https://www.gitbook.com/@rogerzhu/)看到. 如果对和程序员有关 ...

  5. poi 导入导出的api说明(大全)

    原文链接:http://www.cnblogs.com/qingruihappy/p/8443101.html poi 导入导出的api说明(大全) 一. POI简介 ApachePOI是Apache ...

  6. [BZOJ4804]欧拉心算

    题面戳我 题意:求 \[\sum_{i=1}^{n}\sum_{j=1}^{n}\phi(\gcd(i,j))\] 多组数据,\(n\le10^7\). sol SBT 单组数据\(O(\sqrt n ...

  7. 用vmware workstation制作cloudstack(kvm)镜像及问题解决办法

    说明1:vmware workstation镜像是vmdk格式 说明2:cloudstack配置文件目录:/run/libvirt/qemu/     kvm配置文件目录:/etc/libvirt/q ...

  8. eclipse中Maven项目pom.xml报错:com.thoughtworks.xstream.io.HierarchicalStreamDriver

    eclipse中创建Maven项目时 pom.xml报错:com.thoughtworks.xstream.io.HierarchicalStreamDriver 解决方案1.在pom文件中加入mav ...

  9. fitnesse - 框架介绍

    fitnesse - 框架介绍 2017-09-29 目录: 1 fitnesse是什么?2 框架介绍3 与junit.testng比较,fitnesse教其他框架有什么优势 1 fitnesse是什 ...

  10. n皇后问题与2n皇后问题

    n皇后问题 问题描述: 如何能够在 n×n 的棋盘上放置n个皇后,使得任何一个皇后都无法直接吃掉其他的皇后 (任两个皇后都不能处于同一条横行.纵行或斜线上) 结题思路: 可采用深度优先算法,将棋盘看成 ...