Grizzly开发Echoserver实战

作者:chszs,转载需注明。

博客主页:http://blog.csdn.net/chszs

用Java编写可伸缩的server应用是有难度的。用Java NIO开发、线程管理、为成千上万的用户做server扩展。这些都是难点。Grizzly NIO框架的设计目标就是帮助开发人员非常好地利用Java NIO API。编写出高可扩展性的、功能强大的server,并提高了扩展的框架组件:Web Framework(HTTP/S)、WebSocket、Comet等。

Grizzly 2.3开发Echoserver/client的样例

1、下载grizzly-framework.jar库

Maven依赖

<dependency>
<groupId>org.glassfish.grizzly</groupId>
<artifactId>grizzly-framework</artifactId>
<version>2.3.16</version>
</dependency>

或下载地址: http://central.maven.org/maven2/org/glassfish/grizzly/grizzly-framework/2.3.16/grizzly-framework-2.3.16.jar
2014.10.23日刚公布了2.3.17版,地址见: 
https://maven.java.net/content/repositories/releases/org/glassfish/grizzly/grizzly-framework/2.3.17/grizzly-framework-2.3.17.jar
也能够用这个版本号。

server端:

1)创建Echo过滤器
Echo过滤器负责把接收到的消息(无论其类型)原样返回给Grizzly连接。

import java.io.IOException;

import org.glassfish.grizzly.filterchain.BaseFilter;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.filterchain.NextAction; public class EchoFilter extends BaseFilter{ /**
* 仅处理读操作,当消息到来时进行处理
* @param ctx 处理的上下文
* @return 下一个动作
*/
@Override
public NextAction handleRead(FilterChainContext ctx) throws IOException{
// Peer address用于无连接的UDP连接
final Object peerAddress = ctx.getAddress();
final Object message = ctx.getMessage();
System.out.println("Server received: " + message);
ctx.write(peerAddress, message, null);
return ctx.getStopAction();
}
}

2)server初始化代码
全部的server过滤器链都准备好,開始初始化并启动server。

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.logging.Logger; import org.glassfish.grizzly.filterchain.FilterChainBuilder;
import org.glassfish.grizzly.filterchain.TransportFilter;
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder;
import org.glassfish.grizzly.utils.StringFilter; public class EchoServer {
private static final Logger logger = Logger.getLogger(EchoServer.class.getName());
public static final String HOST = "localhost";
public static final int PORT = 7777; public static void main(String[] args) throws IOException{
// 用FilterChainBuilder创建过滤器链
FilterChainBuilder filterChainBuilder = FilterChainBuilder.stateless(); // 加入TransportFilter。它负责从连接中读数据,并写数据到连接
filterChainBuilder.add(new TransportFilter());
// 字符串过滤器StringFilter负责缓冲和字符串之间的转换
filterChainBuilder.add(new StringFilter(Charset.forName("UTF-8")));
// 过滤器EchoFilter负责把接收到的消息原样返回给连接
filterChainBuilder.add(new EchoFilter()); // 创建TCP传输
final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
transport.setProcessor(filterChainBuilder.build());
try{
// 绑定传输,開始对主机+端口进行监听
transport.bind(HOST, PORT);
// 開始传输
transport.start(); logger.info("Press any key to stop the Echo server...");
System.in.read();
} finally{
logger.info("Stopping transport...");
// 停止传输server
transport.shutdown(); logger.info("Stopped transport...");
}
}
}

执行Echoserver:

java -classpath grizzly-framework.jar EchoServer

client:

1)创建client过滤器
client过滤器负责重定向server的响应到标准输出。

要注意,client过滤器须要FilterChainContext消息

import java.io.IOException;

import org.glassfish.grizzly.filterchain.BaseFilter;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.filterchain.NextAction; public class ClientFilter extends BaseFilter{ /**
* 仅处理读操作。当消息到来时进行处理
* @param ctx 处理的上下文
* @return 下一个动作
*/
@Override
public NextAction handleRead(final FilterChainContext ctx) throws IOException{
// 从上下文得到字符串消息,过滤器链仅仅使用了字符串过滤器StringFilter
final String serverResponse = ctx.getMessage();
System.out.println("Server echo: " + serverResponse);
return ctx.getStopAction();
}
}

2)client代码
简单的client,向Echoserver发送消息并等待响应。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Logger; import org.glassfish.grizzly.Connection;
import org.glassfish.grizzly.Grizzly;
import org.glassfish.grizzly.filterchain.FilterChainBuilder;
import org.glassfish.grizzly.filterchain.TransportFilter;
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder;
import org.glassfish.grizzly.utils.StringFilter; import ch.echo.server.EchoServer; public class EchoClient {
private static final Logger logger = Grizzly.logger(EchoClient.class); public static void main(String[] args) throws IOException,
ExecutionException, InterruptedException, TimeoutException{
Connection connection = null; // 用FilterChainBuilder类创建过滤器链
FilterChainBuilder filterChainBuilder = FilterChainBuilder.stateless();
// 加入传输过滤器,它负责从连接读数据并向连接写数据
filterChainBuilder.add(new TransportFilter());
// 加入字符串过滤器,它负责缓冲和字符串之间的转换
filterChainBuilder.add(new StringFilter(Charset.forName("UTF-8")));
// 加入client过滤器,他负责把server响应重定向到标准输出
filterChainBuilder.add(new ClientFilter()); // 创建TCP传输
final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
transport.setProcessor(filterChainBuilder.build()); try{
// 启动传输
transport.start(); // 异步执行。连接到server
Future<Connection> future = transport.connect(EchoServer.HOST, EchoServer.PORT);
// 等待连接操作的完毕
connection = future.get(10, TimeUnit.SECONDS); assert connection!=null;
System.out.println("Ready...(\"q\" to exit");
final BufferedReader inReader = new BufferedReader(new InputStreamReader(System.in));
do{
final String userInput = inReader.readLine();
if(userInput==null || "q".equals(userInput))
break; connection.write(userInput);
} while(true);
} finally{
// 关闭client连接
if(connection!=null)
connection.close(); // 停止传输
transport.shutdownNow();
}
}
}

执行Echoclient:

java -classpath grizzly-framework.jar EchoClient

已经通过測试,程序执行的非常完美。

Grizzly开发Echoserver实战的更多相关文章

  1. 前端开发css实战:使用css制作网页中的多级菜单

    前端开发css实战:使用css制作网页中的多级菜单 在日常工作中,大家都会遇到一些显示隐藏类菜单,比如页头导航.二维码显示隐藏.文本提示等等......而这些效果都是可以使用纯css实现的(而且非常简 ...

  2. 用grunt搭建自动化的web前端开发环境实战教程(详细步骤)

    用grunt搭建自动化的web前端开发环境实战教程(详细步骤) jQuery在使用grunt,bootstrap在使用grunt,百度UEditor在使用grunt,你没有理由不学.不用!前端自动化, ...

  3. NET 分布式架构开发项目实战

    .NET 分布式架构开发项目实战 从头到尾,一步一步讲述一个真实的项目实战,关注点主要是架构的思考和实现,以及如何解决平时项目遇到的一些问题. 同时也司公布源代码. 如何构建高性能,稳定SOA应用之- ...

  4. 《PyQt5快速开发与实战了》正式发售 !!!

    <PyQt5快速开发与实战>正式出售了,该书是国内第一本介绍PyQt5的书籍.是两位一线工程师耗费一年的心血.本书github网址:https://github.com/cxinping/ ...

  5. C# Xamarin移动开发项目实战篇

    一.课程介绍 在前面阿笨的<C# Xamarin移动开发基础进修篇>课程中,大家已经熟悉和了解了Xamarin移动App开发的基础知识和原理.本次分享课<C# Xamarin移动开发 ...

  6. 【Android开发VR实战】二.播放360&#176;全景视频

    转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53924006 本文出自[DylanAndroid的博客] [Android开发 ...

  7. Hbuilder开发app实战-识岁03-文件上传

    前言 做app不得不谈的问题就是文件上传.用hbuilder开发app让上传变的非常easy. Uploader Uploader模块管理网络上传任务,用于从本地上传各种文件到server,并支持跨域 ...

  8. jQuery:[2]百度地图开发平台实战

    jQuery:[2]百度地图开发平台实战 原文链接:   http://blog.csdn.net/moniteryao/article/details/51078779 快速开始 开发平台地址 ht ...

  9. 【Android开发VR实战】三.开发一个寻宝类VR游戏TreasureHunt

    转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53939303 本文出自[DylanAndroid的博客] [Android开发 ...

随机推荐

  1. CentOS6.x升级MySQL版本号5.1到5.6

    有一些虚拟机.云主机提供商仍然使用的是老版本号的安装套件. 预装的应用软件版本号非常低. 比方 techbrood.com 使用的云server,当中MySQL预装版本号为老版本号5.1.x. 而最新 ...

  2. NumberBox( 数值输入框) 组件

    本节课重点了解 EasyUI 中 NumberBox(数值输入框)组件的使用方法,这个组件依赖于 ValidateBox(验证框)组件.一. 加载方式//class 加载方式<input typ ...

  3. Head First HTML与CSS — 为你的页面加图像

    HTML中我们用img标签插入图像,在Web中常用的有三种:JPEG, PNG,GIF. 简单来讲,JPEG适合照片和复杂图像使用,而PNG或GIF适合单色图像.logo.和几何图形使用. JPEG: ...

  4. Function Currying in javascript 的一些注释

    理解函数柯里化(Function Currying ),最关键的是理解下面这个函数: function curry(fn){ var args = Array.prototype.slice.call ...

  5. hdu5392 Infoplane in Tina Town(LCM)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Infoplane in Tina Town Time Limit: 14000/ ...

  6. jQuery自学笔记(三):jQuery动画效果

    jQuery隐藏和显示: 使用 hide( ) 和 show( ) 方法来隐藏和显示 HTML 元素: 语法: $(selector).hide(speed,callback); $(selector ...

  7. 对于js原型和原型链继承的简单理解(第一种,原型链继承)

    原型是js中的难点加重点,也是前端面试官最爱问的问题之一,因为面试官可以通过被面试者对原型的理解.来判断被面试者对js的熟悉程度. 原型的定义 Js所有的函数都有一个prototype属性,这个属性引 ...

  8. 转。webapp开发小tips

     备忘 - Q:  webapp点击一个按钮调用系统拨号: <a href="tel:12345654321">打电话给我</a> <a href=& ...

  9. (转载)Python装饰器学习

    转载出处:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方 ...

  10. C语言初学 比较五个整数并输出最大值和最小值1

    #include<stdio.h> #include<math.h> int max(int x,int y) { if(x>y) return x; else retu ...