Java Netty (2)
通过一个实例来说明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)的更多相关文章
- java netty socket库和自定义C#socket库利用protobuf进行通信完整实例
之前的文章讲述了socket通信的一些基本知识,已经本人自定义的C#版本的socket.和java netty 库的二次封装,但是没有真正的发表测试用例. 本文只是为了讲解利用protobuf 进行C ...
- Java Netty简介
Netty和Mina是Java世界非常知名的通讯框架.它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户netty.io(http:// ...
- 学习 java netty (一) -- java nio
前言:近期在研究java netty这个网络框架,第一篇先介绍java的nio. java nio在jdk1.4引入,事实上也算比較早的了.主要引入非堵塞io和io多路复用.内部基于reactor模式 ...
- [转帖]Java Netty简介
Java Netty简介 https://www.cnblogs.com/ghj1976/p/3779820.html Posted on 2014-06-10 13:41 蝈蝈俊 阅读(2992) ...
- Java Netty 4.x 用户指南
问题 今天,我们使用通用的应用程序或者类库来实现互相通讯,比如,我们经常使用一个 HTTP 客户端库来从 web 服务器上获取信息,或者通过 web 服务来执行一个远程的调用. 然而,有时候一个通用的 ...
- 基于Java Netty框架构建高性能的部标808协议的GPS服务器
使用Java语言开发一个高质量和高性能的jt808 协议的GPS通信服务器,并不是一件简单容易的事情,开发出来一段程序和能够承受数十万台车载接入是两码事,除去开发部标808协议的固有复杂性和几个月长周 ...
- Java+Netty、Vue+Element-UI实现的即时通信应用 leo-im
之前工作接触了几个开源的IM产品,再加上曾经用Netty实现过几个服务,于是就有了用Netty实现一个IM的想法,于是用业余时间写了一个IM,和喜欢Netty的程序员们分享. 考虑到方便扩展,在服务端 ...
- Java Netty (1)
Netty是由JBOSS提供的一个java开源框架,本质上也是NIO,是对NIO的封装,比NIO更加高级,功能更加强大.可以说发展的路线是IO->NIO->Netty. ServerBoo ...
- 基于Java Netty框架构建高性能的Jt808协议的GPS服务器(转)
原文地址:http://www.jt808.com/?p=971 使用Java语言开发一个高质量和高性能的jt808 协议的GPS通信服务器,并不是一件简单容易的事情,开发出来一段程序和能够承受数十万 ...
随机推荐
- CircleImageManager——圆形 / 圆角图片的工具类
这个类可以实现圆角,或者是圆形图片的操作. CircleImageManager.java package com.kale.utils; import android.content.Context ...
- [转]Nginx 502 PHP LNMP 502 终极解决方案 完美解决502 用 upstream 和 fastcgi_next_upstream 可以极大缓解
转: http://xn--ghqyhzj.com/post-21537.html 本文针对LNMP的PHP 版本ver 5.3.6 or Higher,其它未测试过. 1. 使用不同端口或php-f ...
- [转]InnoDB和MyISAM区别
From : http://blog.csdn.net/ghosc/article/details/5391544 MySQL作为当前最为流行的免费数据库服务引擎,已经风靡了很长一段时间,不过也许也有 ...
- WebFormViewEngine及用户控件寻址bug
在做我的网站的时候遇到了主题切换的问题,特总结与大家共享. 熟悉asp.net mvc的朋友都知道,mvc中,默认情况下视图都在views文件夹下放着.要想改变文件必须重写WebFormViewEng ...
- Google和Baidu的站内搜索代码
<!-- SiteSearch Google --> <form method="get" action="http://www.google.com/ ...
- C++ 友元类使用 (friend)
C++中私有变量对外部类是不能直接访问的,也是不能继承的. 使用友元类可以访问类中的私有方法.私有变量,虽然对类的封装有一定的破坏,但是有时也是很实用的. 在实际中,在修改已有代码时,为了不大改动已有 ...
- C/C++二叉树搜索树操作集
啥是二叉查找树 在数据结构中,有一个奇葩的东西,说它奇葩,那是因为它重要,这就是树.而在树中,二叉树又是当中的贵族.二叉树的一个重要应用是它们在查找中的应用,于是就有了二叉查找树. 使二叉树成为一颗二 ...
- SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 (一)在pom.xml中添加依赖: <properties> <shi ...
- js命名空间写法
很早知道这种写法,由于基础面向对象不够扎实一直在回避,但是面对整站这种方法还是有必要会 <div id="div1">111</div> <div i ...
- 命令行修改mysql密码和远程访问
http://jingyan.baidu.com/article/a3a3f8118cea488da2eb8a0a.html