通过一个实例来说明Netty的使用。用1个服务器连接5个客户端线程,客户端连接上服务器以后就向服务器发送消息,服务器接收到消息后向客户端返回消息,客户端接收到消息以后,等待随机的时间,再向服务端发送消息,这样一直循环下去。

项目结构:

NettyServer.java:

package Server;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors; import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor; import Util.Constant; public class NettyServer { public static String host = "127.0.0.1"; // 创建1个线程池
static ExecutionHandler executionHandler = new ExecutionHandler(new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576)); public static void main(String[] args) {
// ChannelFactory
final ChannelFactory channelFactory = new NioServerSocketChannelFactory(
// Boss线程池,处理Socket请求
Executors.newCachedThreadPool(),
// Worker线程池,由于使用的是NIO,1个Worker线程可以管理多个Channel
Executors.newCachedThreadPool());
// ServerBootstrap
ServerBootstrap bootstrap = new ServerBootstrap(channelFactory); ServerPipelineFactory serverPipelineFactory = new ServerPipelineFactory(executionHandler);
bootstrap.setPipelineFactory(serverPipelineFactory); // 禁用nagle算法
bootstrap.setOption("child.tcpNoDelay", true);
// 启用TCP保活检测
bootstrap.setOption("child.keepAlive", true); // 监听5个端口
bootstrap.bind(new InetSocketAddress(Constant.p1));
System.out.println("Listening port " + Constant.p1 + "...");
bootstrap.bind(new InetSocketAddress(Constant.p2));
System.out.println("Listening port " + Constant.p2 + "...");
bootstrap.bind(new InetSocketAddress(Constant.p3));
System.out.println("Listening port " + Constant.p3 + "...");
bootstrap.bind(new InetSocketAddress(Constant.p4));
System.out.println("Listening port " + Constant.p4 + "...");
bootstrap.bind(new InetSocketAddress(Constant.p5));
System.out.println("Listening port " + Constant.p5 + "...");
} }

ServerPipelineFactory.java:

package Server;

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.execution.ExecutionHandler; public class ServerPipelineFactory implements ChannelPipelineFactory { private final ExecutionHandler executionHandler; public ServerPipelineFactory(ExecutionHandler executionHandler){
this.executionHandler = executionHandler;
} @Override
public ChannelPipeline getPipeline() throws Exception {
// TODO Auto-generated method stub
return Channels.pipeline(
new StringEncoder(),
new StringDecoder(),
// 多个pipeline之间必须共享同一个ExecutionHandler,放在业务逻辑handler之前
executionHandler,
// 业务逻辑handler
new MyServerHandler());
} }

MyServerHandler.java:

package Server;

import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import Util.Tool; public class MyServerHandler extends SimpleChannelHandler{ @SuppressWarnings("static-access")
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("Server received:" + e.getMessage());
// 休息随机秒后发送消息
Thread th = Thread.currentThread();
int interval = Tool.getInterval(100);
th.sleep(interval*1000);
e.getChannel().write("from Server: Hello!");
super.messageReceived(ctx, e);
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
e.getCause().printStackTrace();
Channel ch = e.getChannel();
ch.close();
super.exceptionCaught(ctx, e);
} @Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("A client connected!");
super.channelConnected(ctx, e);
} }

NettyClient.java:

package Client;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors; import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor; import Util.Constant; public class NettyClient extends Thread{ public static String host = "127.0.0.1";
ClientBootstrap bootstrap;
int port; // 创建1个线程池
static ExecutionHandler executionHandler = new ExecutionHandler(new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576)); public NettyClient(int port) {
this.port = port;
// ChannelFactory
final ChannelFactory channelFactory = new NioClientSocketChannelFactory(
// Boss线程池
Executors.newCachedThreadPool(),
// Worker线程池
Executors.newCachedThreadPool());
// ServerBootstrap
bootstrap = new ClientBootstrap(channelFactory); ClientPipelineFactory clientPipelineFactory = new ClientPipelineFactory(executionHandler);
bootstrap.setPipelineFactory(clientPipelineFactory);
bootstrap.setOption("tcpNoDelay" ,true);
bootstrap.setOption("keepAlive", true);
bootstrap.connect(new InetSocketAddress(port)); } public void run(){
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// 开始试图连接
System.out.println("Connecting to port " + port + "...");
// 等待直到连接关闭或失败
future.getChannel().getCloseFuture().awaitUninterruptibly();
// 关闭线程池准备退出
bootstrap.releaseExternalResources();
} public static void main(String[] args) {
NettyClient nc1 = new NettyClient(Constant.p1);
NettyClient nc2 = new NettyClient(Constant.p2);
NettyClient nc3 = new NettyClient(Constant.p3);
NettyClient nc4 = new NettyClient(Constant.p4);
NettyClient nc5 = new NettyClient(Constant.p5); nc1.start();
nc2.start();
nc3.start();
nc4.start();
nc5.start();
} }

ClientPipelineFactory.java:

package Client;

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.execution.ExecutionHandler; public class ClientPipelineFactory implements ChannelPipelineFactory { private final ExecutionHandler executionHandler; public ClientPipelineFactory(ExecutionHandler executionHandler){
this.executionHandler = executionHandler;
} @Override
public ChannelPipeline getPipeline() throws Exception {
// TODO Auto-generated method stub
return Channels.pipeline(
new StringEncoder(),
new StringDecoder(),
// 多个pipeline之间必须共享同一个ExecutionHandler,放在业务逻辑handler之前
executionHandler,
// 业务逻辑handler
new MyClientHandler());
}
}

MyClientHandler.java:

package Client;

import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler; import Util.Tool; public class MyClientHandler extends SimpleChannelHandler{ // 连接到服务端时,发出消息
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("Connected to Server!");
e.getChannel().write("from Client: Hello! " + System.currentTimeMillis());
super.channelConnected(ctx, e);
} @SuppressWarnings("static-access")
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
System.out.println("Client Received:" + e.getMessage());
// 休息随机秒后发送消息
Thread th = Thread.currentThread();
int interval = Tool.getInterval(5);
th.sleep(interval*1000);
e.getChannel().write("from Client: Hello! " + System.currentTimeMillis());
super.messageReceived(ctx, e);
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
e.getCause().printStackTrace();
Channel ch = e.getChannel();
ch.close();
super.exceptionCaught(ctx, e);
} }

Constant.java:

package Util;

public class Constant {
final static int start = 10000;
public static int p1 = start + 1;
public static int p2 = start + 2;
public static int p3 = start + 3;
public static int p4 = start + 4;
public static int p5 = start + 5;
}

Tool.java:

package Util;

import java.util.Random;

public class Tool {

    static Random rand = new Random();

    public static int getInterval(int max){
return rand.nextInt(max);
}
}

Java Netty (2)的更多相关文章

  1. java netty socket库和自定义C#socket库利用protobuf进行通信完整实例

    之前的文章讲述了socket通信的一些基本知识,已经本人自定义的C#版本的socket.和java netty 库的二次封装,但是没有真正的发表测试用例. 本文只是为了讲解利用protobuf 进行C ...

  2. Java Netty简介

    Netty和Mina是Java世界非常知名的通讯框架.它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户netty.io(http:// ...

  3. 学习 java netty (一) -- java nio

    前言:近期在研究java netty这个网络框架,第一篇先介绍java的nio. java nio在jdk1.4引入,事实上也算比較早的了.主要引入非堵塞io和io多路复用.内部基于reactor模式 ...

  4. [转帖]Java Netty简介

    Java Netty简介 https://www.cnblogs.com/ghj1976/p/3779820.html Posted on 2014-06-10 13:41 蝈蝈俊 阅读(2992) ...

  5. Java Netty 4.x 用户指南

    问题 今天,我们使用通用的应用程序或者类库来实现互相通讯,比如,我们经常使用一个 HTTP 客户端库来从 web 服务器上获取信息,或者通过 web 服务来执行一个远程的调用. 然而,有时候一个通用的 ...

  6. 基于Java Netty框架构建高性能的部标808协议的GPS服务器

    使用Java语言开发一个高质量和高性能的jt808 协议的GPS通信服务器,并不是一件简单容易的事情,开发出来一段程序和能够承受数十万台车载接入是两码事,除去开发部标808协议的固有复杂性和几个月长周 ...

  7. Java+Netty、Vue+Element-UI实现的即时通信应用 leo-im

    之前工作接触了几个开源的IM产品,再加上曾经用Netty实现过几个服务,于是就有了用Netty实现一个IM的想法,于是用业余时间写了一个IM,和喜欢Netty的程序员们分享. 考虑到方便扩展,在服务端 ...

  8. Java Netty (1)

    Netty是由JBOSS提供的一个java开源框架,本质上也是NIO,是对NIO的封装,比NIO更加高级,功能更加强大.可以说发展的路线是IO->NIO->Netty. ServerBoo ...

  9. 基于Java Netty框架构建高性能的Jt808协议的GPS服务器(转)

    原文地址:http://www.jt808.com/?p=971 使用Java语言开发一个高质量和高性能的jt808 协议的GPS通信服务器,并不是一件简单容易的事情,开发出来一段程序和能够承受数十万 ...

随机推荐

  1. 架构:The Clean Architecture(整洁的架构)(转载)

    地址:http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html. Over the last several ...

  2. ios开发经常使用RGB色值

    iOS中RGB经常使用的色值,同一时候可将对颜色的设置定义成宏,方便开发应用,如: // RGB颜色转换(16进制->10进制) #define UIColorFromRGB(rgbValue) ...

  3. 点击cell动态修改高度动画

    点击cell动态修改高度动画 效果 源码 https://github.com/YouXianMing/Animations // // TapCellAnimationController.m // ...

  4. Xcode下修改plist文件

    plist文件在Mac OS下的重要性,如同Windows下的注册表文件.而很多场景下面,我们需要修改plist文件来实现一些"自动化"操作   Mac OS本身提供了一个工具:P ...

  5. 开源项目PullToRefresh详解(四)——PullToRefreshListView和ViewPager的结合使用

    其实这个不是什么新东西了,在介绍(一)中我们就知道了PullToRefreshListView的用法,这里只要将其放入到ViewPager中就行啦.ViewPager还是和以往一样的定义和使用,在适配 ...

  6. MySQL Test Suite使用

    MySQL Test Suite使用 MySQL自动测试套件(The MySQL Test Suite)用于对MySQL程序进行测试,包括各种功能与存储引擎.包含于MySQL与MariaDB版本代码中 ...

  7. iPhone跳转的动画效果类型及实现方法 CATransition

    实现iphone漂亮的动画效果主要有两种方法,一种是UIView层面的,一种是使用CATransition进行更低层次的控制, 第一种是UIView,UIView方式可能在低层也是使用CATransi ...

  8. Focal Loss(RetinaNet) 与 OHEM

    Focal Loss for Dense Object Detection-RetinaNet YOLO和SSD可以算one-stage算法里的佼佼者,加上R-CNN系列算法,这几种算法可以说是目标检 ...

  9. HTML5读取本地文件

    本文转自:转:http://hushicai.com/2014/03/29/html5-du-qu-ben-di-wen-jian.html感谢大神分享. 常见的语言比如php.shell等,是如何读 ...

  10. Mahout源码目录说明

    http://www.cnblogs.com/dlts26/archive/2011/08/23/2150230.html mahout项目是由多个子项目组成的,各子项目分别位于源码的不同目录下,下面 ...