通过一个实例来说明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. WordPress主题开发:开启导航菜单功能

    步骤一:开启导航菜单功能 <?php /* register_nav_menu( $location, $description ) 函数功能:开启导航菜单功能 @参数 string $loca ...

  2. how to use kvo with swift (怎样在swift中使用kvo)

  3. Android之用自定义的shape去实现shadow效果

    直接上xml文件, 并且附上相应的解析: <?xml version="1.0" encoding="utf-8"?> <selector x ...

  4. MongoDB索引,性能分析

    索引的限制: 索引名称不能超过128个字符 每个集合不能超过64个索引 复合索引不能超过31列 MongoDB 索引语法 db.collection.createIndex({ <field&g ...

  5. Spring data jpa Specification查询关于日期的范围搜索

    代码: 时间格式化类型: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat s ...

  6. C# WebBrowser控件使用整理

    一.简介 WebBrowser 控件为 WebBrowser ActiveX 控件提供了托管包装. 托管包装使您可以在 Windows 窗体客户端应用程序中显示网页. 使用WebBrowser 控件, ...

  7. Zookeeper Tutorial 2 -- Programmer's Guide

    数据模型 ZooKeeper跟分布式文件系统一样, 有一系列的命名空间. 唯一不同的地方是命名空间中的每个节点都有数据和他相关联. 它类似于一个允许文件同时是一个目录的文件系统. 节点的路径永远是以斜 ...

  8. 【BZOJ】【4152】【AMPZZ2014】The Captain

    最短路 题解:http://zyfzyf.is-programmer.com/posts/97953.html 按x坐标排序,相邻点之间连边.满足dist(x1,x3)<=dist(x1,x2) ...

  9. 什么是L2 frame?

    The data link layer or layer 2 is the second layer of the seven-layer OSI model of computer networki ...

  10. seleium 鼠标悬停事件

    seleium 教程:https://www.yiibai.com/selenium seleium官网:https://www.seleniumhq.org/docs/ 1.鼠标悬停 例如,下图 鼠 ...