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. AHCI模式安装XP以及驱动下载

    一.准备AHCI驱动 1.关于AHCI基础知识,请参考<AHCI模式的驱动下载.安装及蓝屏问题综合>一文. 2.安装AHCI驱动之前,请先确认桌面上.系统盘没有重要的东西需要备份,因为如果 ...

  2. RHEL简单管理SELINUX

    Security Enhanced Linux(SELinux)是一个额外的系统安全层,主要目的是防止已遭泄露的系统服务访问用户数据. 对于一个服务来说,要关注SELinux的三个方面,一是文件SEL ...

  3. iOS - CALayer 绘图层

    1.CALayer 绘图层 在 iOS 系统中,你能看得见摸得着的东西基本上都是 UIView,比如一个按钮.一个文本标签.一个文本输入框.一个图标等等,这些都是 UIView.其实 UIView 之 ...

  4. 消息队列mq的原理及实现方法

    消息队列技术是分布式应用间交换信息的一种技术.消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读走.通过消息队列,应用程序可独立地执行--它们不需要知道彼此的位置.或在继续执行前不需要等待 ...

  5. thinkphp在mac下报错

    简要:众所周知,开发软件最好的环境是在MAC下;为此在黑苹果上,用Thinkphp开发;在过程中出现,找不到model以及数据库类型错误;为此向大家分享解决办法,希望能够帮助困惑的伙伴们,如果有不对或 ...

  6. Android动态类生成预加载-dexmaker使用

    一.dexmaker简单介绍 dexmaker是运行在Android Dalvik VM上,利用Java编写,来动态生成DEX字节码的API.如果读者了解AOP编程的话,应该听说过cglib or A ...

  7. 自己写的,然后配合zepto+iscroll的上拉加载

    /** * Created by jl on 2016/3/28. *///初始化绑定iScroll控件var actHtml="";var myScroll,    pullUp ...

  8. [HNOI2011]XOR和路径 && [HNOI2013]游走

    [HNOI2011]XOR和路径 题目大意 具体题目:戳我 题目: 给定一个n个点,m条边的有重边.有自环的无向图,其中每个边都有一个边权. 现在随机选择一条1到n的路径,路径权值为这条路径上所有边权 ...

  9. Bzoj4555: [Tjoi2016&Heoi2016]求和

    题面 Bzoj Sol 推柿子 因为当\(j>i\)时\(S(i, j)=0\),所以有 \[\sum_{i=0}^{n}\sum_{j=0}^{n}S(i, j)2^j(j!)\] 枚举\(j ...

  10. TypeScript入门知识一(字符串特性)

    一,TypeScript多行字符串 传统JavaScript字符串换行需要+进行拼接,而TypeScript不需要+拼接.看下面实例: javaScript: var content = " ...