Grizzly开发Echoserver实战

Grizzly开发Echoserver实战

大家好,又见面了,我是全栈君。

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115753.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • futureTask使用[通俗易懂]

    futureTask使用[通俗易懂]List<FutureTask>taskList=newArrayList<>();if(leaderList!=null&&!leaderList.isEmpty()){leaderList.forEach(userId->{…

    2022年6月15日
    52
  • 体育赛事视频直播方案「建议收藏」

    体育赛事视频直播方案「建议收藏」播已经走入千家万户。各种领域的直播应用、平台如雨后春笋般的涌现。这当然也包括各种体育赛事的直播如篮球赛事直播,足球赛事直播,排球赛事直播等等。对于体育迷来说,NBA、西甲、英超、德甲、意甲、中超、CBA这些比赛是最熟悉不过的了。作为观赏赛事者有很多选择:Zhibo.tv: 直播TV最精彩的体育娱乐直播平台。乐视体育: 让每个人更好的参与体育。企鹅直播: 最全体育赛事视频直播平台。

    2022年7月23日
    21
  • [Arm]使用modprobe时 “modprobe: can‘t change directory to …”

    [Arm]使用modprobe时 “modprobe: can‘t change directory to …”最近在加载一个叫dmatest的模块时,报错modprobe:can’tchangedirectoryto’…’:Nosuchfileordirectory,做一个问题记录。首先,modprobe的解释:modprobe是linux的一个命令,可载入指定的个别模块,或是载入一组相依的模块。modprobe会根据depmod所产生的相依关系,决定要载入哪些模块。若…

    2025年7月5日
    3
  • java中|与||,&与&&到底有什么区别呢?

    java中|与||,&与&&到底有什么区别呢?在java中,很多人都不知道&与&&,|与||的区别。&,&&:(与,短路与):一样的地方就是二者执行最后的结果是一样的,但是执行的过程有区别,对于&:无论&左边是否为false,他都会继续检验右边的boolean值。对于&&:只要检测到左边Boolean值为false时,就会直接判断结果,不会在检验右边的值(因为”与”有一个false最后结果就是false了)所以&&的执行效率更

    2022年7月7日
    26
  • 【JAVA】Java学习路线图「建议收藏」

    【JAVA】Java学习路线图「建议收藏」怎么学习Java,这是很多新手经常会问我的问题,现在我简单描述下一个Java初学者到就业要学到的一些东西:    首先要明白Java体系设计到得三个方面:J2SE,J2EE,J2ME(KJAVA)。J2SE,Java2PlatformStandardEdition,我们经常说到的JDK,就主要指的这个,它是三者的基础,属于桌面级应用开发,这部分如果学得好很容易拓展J2EE和J2ME。

    2022年5月15日
    34
  • acwing1057. 股票买卖 IV(状态机模型)

    acwing1057. 股票买卖 IV(状态机模型)给定一个长度为 N 的数组,数组中的第 i 个数字表示一个给定股票在第 i 天的价格。设计一个算法来计算你所能获取的最大利润,你最多可以完成 k 笔交易。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。一次买入卖出合为一笔交易。输入格式第一行包含整数 N 和 k,表示数组的长度以及你可以完成的最大交易数量。第二行包含 N 个不超过 10000 的正整数,表示完整的数组。输出格式输出一个整数,表示最大利润。数据范围1≤N≤105,1≤k≤100输入样例1:3 22

    2022年8月9日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号