15
Apr
April 15, 2014 分类: Java     作者: hoverlees     留言: 发表

servlet 3是servlet的升级,tomcat在第7版本以后实现了该标准,最主要的特性就是加入了请求异步处理的功能。

异步是网络中最常用最高效的处理模型,通过异步,就可以实现让当前请求先保持连接,让cpu去处理其他的请求,当满足某个条件时再回来处理这个连接。

有了异步功能,我们的服务器就可以实现如下的一些功能:

1. long-polling长轮询

2. websocket等持久连接

异步主要通过Servlet的startAsync完成,这个函数返回AsyncContext,可以通过对AsyncContext设置超时和事件监听。如果超时没有处理,连接就会自动断开并调用事件监听器的onTimeout,程序可以在onTimeout中进行处理,如果调用了AsyncContext的complete,连接则会正常关闭,否则会抛错。

AsyncListener包含如下函数:

void onComplete(AsyncEvent event); //当异步处理完成时调用
void onError(AsyncEvent event); //当出错时调用,比如超时了但没有调用complete
void onStartAsync(AsyncEvent event); //当开始进入异步状态时调用,即调用startAsync时
void onTimeout(AsyncEvent event); //当超时的时候调用

其中要注意的是onStartAsync,由于AsyncContext是在ServletRequest的startSync后才能获取到,获取后才能添加listener,所以第一次的onStartAsync是不会被调用到的,但由于ServletRequest的startSync可以多次调用,所以当下次startSync时,onStartAsync才会被调用到。

最后要注意的的是servlet需要标记async=true

@WebServlet(asyncSupported = true)

并在startAsync之前添加如下设置

request.setAttribute(“org.apache.catalina.ASYNC_SUPPORTED”, true);

04
Apr
April 4, 2014 分类: Java     作者: hoverlees     留言: 发表

较早的java版本没有直接提供base64编码处理的类,都是通过其他类库的附加功能实现。而对于android平台,又有自己的base64支持类,导致代码影响跨平台。所以就自己写了个base64编码处理的类,这样就可以同一套代码运行在android平台和se平台了。
代码如下:

package com.hoverlees.utils;

/**
 * @author hoverlees http://www.hoverlees.com
 * RFC 4648
 */
public class Base64 {
	private static char[] base64Table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
	private static byte[] base64TableMap=createTableMap();
	private static byte[] createTableMap() {
		byte[] table=new byte[256];
		for(int i=0;i<256;i++) table[i]=-1;
		for(int i=0;i<base64Table.length;i++){
			table[base64Table[i]]=(byte)i;
		}
		return table;
	}
	/**
	 * Base64编码,将字节数组转换成base64字符串
	 * @param data 字节数据
	 * @return base64编码的字符串
	 */
	public static String encode(byte[] data){
		StringBuffer s=new StringBuffer();
		int state=0;
		int pos=0;
		for(int i=0;i<data.length;i++){
			switch(pos){
			case 0:
				state=(data[i]&0xFC)>>2;
				s.append(base64Table[state]);
				state=(data[i]&0x3)<<4;
				pos=1;
				break;
			case 1:
				state|=((data[i]&0xF0)>>4);
				s.append(base64Table[state]);
				state=(data[i]&0xF)<<2;
				pos=2;
				break;
			case 2:
				state|=((data[i]&0xC0)>>6);
				s.append(base64Table[state]);
				state=data[i]&0x3F;
				s.append(base64Table[state]);
				pos=0;
				break;
			}
		}
		if(pos==1){
			s.append(base64Table[state]);
			s.append("==");
		}
		else if(pos==2){
			s.append(base64Table[state]);
			s.append("=");
		}
		return s.toString();
	}
	/**
	 * Base64解码,将base64字符串转换成字节数组
	 * @param data base64的字符串
	 * @return 解码后的字节数组
	 */
    public static byte[] decode(String data){
        byte[] bytes=data.getBytes();
        int n=0;
        int pos=0;
        byte cchar,t;
        for(int i=0;i<bytes.length;i++){
            cchar=bytes[i];
            t=base64TableMap[cchar];
            if(cchar=='=') break;
            switch(pos){
            case 0:
                bytes[n]=(byte)(t<<2);
                pos=1;
                break;
            case 1:
                bytes[n]=(byte)(bytes[n]|((t&0x30)>>4));
                n++;
                bytes[n]=(byte)((t&0xf)<<4);
                pos=2;
                break;
            case 2:
                bytes[n]=(byte)(bytes[n]|((t&0x3c)>>2));
                n++;
                bytes[n]=(byte)((t&0x3)<<6);
                pos=3;
                break;
            case 3:
                bytes[n]=(byte)(bytes[n]|t);
                n++;
                pos=0;
                break;
            }
        }
        byte[] r=new byte[n];
        for(int i=0;i<n;i++) r[i]=bytes[i];
        return r;
    }
}

标签:
28
Mar
March 28, 2013 分类: Java     作者: hoverlees     留言: 2

这是一个封装好的WebSocket服务器,通过简单的扩展就可以实现基于websocket的服务。写这个工具的主要目的是为了用于方便websocket应用的前端和服务器同时开发。

比如做HTML5游戏一般都是服务器和客户端同时开发。在开发之前最重要的就是制定通信协议,但游戏客户端在开发时可能需要调用接口,此时如果服务器端还未实现的话,就可能影响客户端的开发工作,用这个就可以解决问题。

可以在开发游戏客户端前,完成通信接口的简单实现,下面是一个调用示例:

import org.json.JSONException;
import org.json.JSONObject;

import com.hoverlees.ws.*;

public class Test implements WebSocketHandler {
	private int id=1;
	public Test(){
		WebSocketServer server;
		server=new WebSocketServer(8766);
		server.setHandler("/", this);
		try {
			server.start();
		} catch (WebSocketServerException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args){
		new Test();
	}

	@Override
	public void onConnect(WebSocketServer server,WebSocketSession session) {
		System.out.println("用户["+id+"]进入.");
		session.userData=id;
		id++;
		server.sendPacket(session, ("Hello!".getBytes()));
	}
	@Override
	public void onPacket(WebSocketServer server,WebSocketSession session, WebSocketPacket packet) {
		System.out.println("收到用户["+session.userData+"]数据: \""+packet.getStringData()+"\"");
		try{
			JSONObject obj=new JSONObject(packet.getStringData());
			String cmd=obj.getString("cmd");
			if(cmd.equals("add")){
				int sum=obj.getInt("a")+obj.getInt("b");
				server.sendPacket(session, ("a+b="+sum).getBytes());
			}
			else if(cmd.equals("sub")){
				int sub=obj.getInt("a")-obj.getInt("b");
				server.sendPacket(session, ("a-b="+sub).getBytes());
			}
		}catch(JSONException e){
			e.printStackTrace();
		}
	}
	@Override
	public void onDisconnect(WebSocketServer server,WebSocketSession session) {
		System.out.println("用户["+session.userData+"]退出.");
	}
}


查看详细内容 »

24
Dec
December 24, 2012 分类: Java     作者: hoverlees     留言: 发表

没事翻翻移动硬盘,发现了07年做的空当接龙游戏,真是一个古董了啊.居然还可以在我的ubuntu上跑得很顺畅.时间过得真快…

下面给大家提供jar文件下载.嘿嘿.

空当接龙jar文件.

06
Apr
April 6, 2012 分类: ASM/C/C++, Java     作者: hoverlees     留言: 3

本来想玩玩android的网络应用,特地买了一个htc G12手机来做实验,首先实验了p2p,发现不同的网络运营商根本打不通(为此,我还特地分析了QQ 的解决方式,他们也是走TCP的),后来想想p2p实现在这种场合根本没有太多意义,自已要实现数据包的顺序,校验,还不如用tcp.后来就做成了服务器转发方式。

可惜,我的htc被小偷偷了,准备还是用iphone 4s了,所以这个代码也不打算写了,有兴趣的人可以拿去参考参考。

服务器使用的还是java的nio方式,心得就是调用方式是和epoll最像,epoll的方式是在发送数据前注册EPOLLOUT事件,然后在有缓冲区可以发送数据时就能收到这个事件,在这个事件收到时进行数据包发送,当数据包发送完成后再取消注册EPOLLOUT事件即可,这样就不用判断是否有缓冲可以发送数据了。java nio的select 就相于epoll_wait。

相比于 windows上的io completion port方式,不同的就是数据发送。iocp发送数据是不管怎样,先把你的数据通过WSASend加到发送队列,然后内核会帮你按顺序发送这个队列,当发送完成后会通知应用程序。他们的差别在于通知是一先一后的关系,但都是最高效的。所以我猜想windows平台上的java nio实现就是只要你注册了监听写事件时就会循环收到写事件而不管缓冲区是否为空。

这是一个eclipse工程,com.hoverlees下的为android客户端程序,com.astream是拿udp做p2p的实验程序.com.astream.Server为服务器程序,Client.java为命令行客户端。

已实现的功能:

1.查看用户列表

2.选择用户进行聊天

3.可发送文本,图片,视频,语音

4.可发送离线文件。

界面比较丑,因为是做着玩的。

整个工程下载

03
Jun
June 3, 2011 分类: Java     作者: hoverlees     留言: 1

上一篇文章简单说明了java反射机制及其一些基本操作,这篇文章就简单写一下它的应用。

本文地址: http://www.hoverlees.com/blog/?p=539

反射机制可以应用的地方还包括函数跳转表,脚本执行等,函数跳转表常用在多路判断上,以达到线性时间判断的效果。跳转表常用在流解析等应用上,比如说解析xml,解析脚本等,我们可以做一个长度为256的跳转表,每读入一个字节直接跳到指定处理的代码段,从而不用在判断上浪费CPU。用反射机制实现的跳转表,可以使用Method数组实现。当然,跳转表这儿,我推荐的方法是接口数组实现跳转表。例如你定义一个interface包含一个函数,然后定义一个接口数组,每个接口不同的实现即可。

本文的例子是脚本执行,为了让下面的字符串执行起来。

sget
stdout,java.lang.System,out
String
info,=========Output by commands=========
invoke
r,stdout,println,java.lang.String,info
new
t1,com.hoverlees.reflect.TestClass
invoke
can_next,t1,next
while
can_next
invoke
r,t1,doit
invoke
can_next,t1,next
endwhile

第一行是命令,第二行是参数。说明我就写在代码里了,就不多说了,直接看代码。


查看详细内容 »

11
May
May 11, 2011 分类: Java     作者: hoverlees     留言: 发表

很久没有写点文章了,最近工作很忙,私事很多.

最近在做android软件的架构,虽然,我自己并不喜欢编写java程序,但现在没有android 开发的人手,需要我先把底层的架构做好,边做边招人…

此连载打算写两篇,本文主要打算讨论Java的反射机制的基本原理和相关类,下一篇写反射机制的一个应用.

本文链接 http://www.hoverlees.com/blog/?p=513

Java,本身是一门非常优秀的面向对象语言,严格的面向对象语法,跨平台,学习简单…使用相当广泛,它的优秀是无可厚非的,但它也有一些争议,比如class文件的半编译方式会降底系统性能,还有单继承的限制有时候让人不爽(可以理解,但这点我支持java的方式),还有最重要的就是Java导致很多开发人员只会编代码,而对很多计算机科学应该知道的知识不了解.因为Java太上层了.但如果一个java出生的程序员又对计算机科学有广泛的爱好,那java可以带来很多面向对象编程,架构等等的思路指导.而且现在很多的脚本语言都是趋近于java的语法,如果你能理解Java的精髓,那么Javascript,Flash的ActionScript,甚至PHP对你来说都很简单(我就是这样).当然相关方面应用的知识是一定要知道的~程序语言只是工具而已!!

Java的应用很广泛,桌面程序,服务器应用,手持设备,其它设备基本上都支持由java来驱动.我们也可以扩展Java虚拟机(JNI,或源代码级修改)(哈哈,这是我最喜欢做的事了),使自己的Java虚拟机可以提供自己的包给上层开发人员调用,这些包可能直接操作设备,也可能是像支付功能一样的那些”只能让少数重要的人员维护”的功能.

吹了这么多废话,说说Java的反射机制吧,通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们.


查看详细内容 »