flash摇号程序

朋友圣诞节搞晚会要用的,就帮忙做了个.可以设置号码范围,可以一次抽1-10个号不等.

摇过的号不会重复出现,具体操作可以看附带的帮助文件.背景可以修改.用得着的人也可以拿去用用.

演示地址: http://www.hoverlees.com/diy/lottery/lucky.swf

下载地址:http://www.hoverlees.com/diy/lottery/lucky.zip

基于websocket的火拼俄罗斯

有vps就是好! 抽了几个周末的空闲时间完成了火拼俄罗斯的websocket服务器及客户程序,现在已经支持新版的websocket协议和苹果设备支持的websocket协议. 做这个的初衷是为了几个人在一起无聊的时候可以用手机连机玩些小游戏打发无聊时光.本人已经测试即使走最慢的移动的Edge网络,也不影响相互连机.

火拼俄罗期电脑的玩法跟QQ游戏的一样,上下左右方向键控制移动和旋转,空格直接下落,数字1,2,3,4使用道具给指定号码的玩家.

手机是通过在屏幕任意位置滑动时左右移动,点击自己游戏区域的上部变形,点击自己游戏区域的下部分下落,点击玩家编号向指定玩家使用道具.

游戏大厅地址: http://www.hoverlees.com/game

这个是直接登录链接: 点击这里直接登录

Continue reading “基于websocket的火拼俄罗斯”

WebSocket握手总结

经过本人对WebSocket协议的研究和WebSocket服务器的编写,对WebSocket有了深入的了解,在此写个总结供以后研究参考。

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

1.概要

WebSocket是最新提出用于实现服务器与浏览器双向通信的一种解决方案,用于取代一些传统的数据推送方案(如iframe长连接,ajax轮询等)。该方案由于一直在草案阶段,最新的版本为version 13.该版本出现在RFC6455中。而在safari(包括桌面和移动版本)上则是使用的websocket的 draft-ietf-hybi版。照这个趋势看来,WebSocket早晚会向RFC6455的方向定型。

在本文中,称RFC6455版的chrome版,safari使用的版本为safari版。

Continue reading “WebSocket握手总结”

教大家一招javascript最简单解析json的方法

json本来就是使用javascript语法,所以javascrpit自己就可以解析json.大胆猜测我这个函数在IE6浏览器上也没有问题,比JSON类兼容性还好.

写个示例给大家:

function jsonParse(json){
    json="a="+json;
    return eval(json);
}
//解析json串 {"a":"\u4e2d\u6587","b":"xixi","d":{"a":1},"f":[1,2,3,4,5,6]}
var json='{"a":"\\u4e2d\\u6587","b":"xixi","d":{"a":1},"f":[1,2,3,4,5,6]}'; //注意这个多个斜杠只是转义
var obj=jsonParse(json);
alert(obj.a);

运行结果,输出”中文”二字.

如果要让老版浏览器兼容JSON类,可以像下面这样实现:

if(typeof(JSON)=='undefined'){
     window.JSON={
     	parse:function(json){
     		return eval("a="+json);     	
     	}     
     };
}

自己实现的WebSocket服务器数据包处理函数

最近在写WebSocket的服务器,打算同时做基于websocket的游戏及游戏服务器。研究了一下WebSocket协议,然后基于epoll写了一个websocket的服务器,可支持超大并发量^_^,这儿向大家提供数据包解析和创建的函数,供大家学习参考。

功能参考RFC 6455 ,目前最新的websocket v13版本的协议写成。支持mask和非mask两种方式,支持解析和创建数据长度在6K以下的WebSocket数据包。
这儿只是个解析示例,现实的网络开发中应使用流解析方式生成,流方式的实现即通过向一个状态机添加缓冲区,当状态机组合出一个包头时回调。

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

//websocket.h

/**
 * WebSocket数据包解析和生成函数,RFC 6455 WebSocket V13 标准
 * @author Hoverlees  http://www.hoverlees.com
 */
#ifndef __HOVERLEES_WEBSOCKET_H
#define __HOVERLEES_WEBSOCKET_H

#define OPCODE_CONTINUATION	0
#define OPCODE_TEXT			1
#define OPCODE_BINARY		2
#define OPCODE_CLOSE		8
#define OPCODE_PING			9
#define OPCODE_PONG			10

typedef struct WebSocketPacket{
	unsigned char fin;
	unsigned char mask;
	unsigned char opcode;
	unsigned char mask_key[4];
	int data_len;
	unsigned char* data;
}WebSocketPacket;

int websocket_packet_parse(unsigned char* mem,int len,WebSocketPacket* packet,int data_len);
int websocket_packet_build(unsigned char* data,int len,WebSocketPacket* packet);

#endif

//websocket.c
/**
 * 解析WebSocket数据包 ,参考RFC 6455 page27 
 * http://tools.ietf.org/html/rfc6455#page-27
 * @param mem 数据包内存
 * @param len 数据包长度
 * @param packet 解析后的数据将存到这个对象中,请在传入packet之前初始化packet的data指针指向一块可用内存.
 * @param data_len packet的内存块可接收的最大字节数
 * @return 如果解析成功返回1,解析失败返回0
 */
int websocket_packet_parse(unsigned char* mem,int len,WebSocketPacket* packet,int data_len){
	int i,j;
	int pos;
	pos=2;
	i=mem[1]&127;
	if(i==127){
		//大于65536的数据包不适合用这种解析方式。应该使用流解析方式。
		return 0;
	}
	else if(i==126){
		i=mem[2]*256+mem[3];
		pos=4;
	}
	if(i>data_len) return i-data_len;
	packet->fin=(mem[0]&128) ? 1:0;
	packet->opcode=mem[0]&0xf;
	packet->mask=mem[1]&128;
	packet->data_len=i;
	if(packet->mask){
		for(i=0;i<4;i++){
			packet->mask_key[i]=mem[pos+i];
		}
		pos+=4;
		for(i=0;i<packet->data_len;i++){
			j=i%4;
			packet->data[i]=mem[pos+i]^packet->mask_key[j];
		}
	}
	else{
		for(i=0;i<packet->data_len;i++){
			packet->data[i]=mem[pos+i];
		}
	}
	packet->data[i]=0;
	return 1;
}
/**
 * 创建数据包
 * @param data 要发送的数据实体
 * @param len 数据长度
 * @param packet 数据包,生成的数据在数据包的data中,传入前请先初始化data指针以及需要的参数
 * @return 最终生成的块大小 
 */
int websocket_packet_build(unsigned char* data,int len,WebSocketPacket* packet){
	int pos=0;
	int i,j;
	if(len>65528) return 0;
	packet->data[0]=packet->fin? 128:0;
	packet->data[0]|=packet->opcode;
	if(len>=126){
		packet->data[1]=126;
		packet->data[2]=(len>>8)&0xFF;
		packet->data[3]=len&0xFF;
		pos=4;
	}
	else{
		packet->data[1]=len&0xFF;
		pos=2;
	}
	packet->mask=0; //为了支持稍老一点的浏览器
	if(packet->mask){
		packet->data[1]|=128;
		for(i=0;i<4;i++){
			packet->data[pos+i]=packet->mask_key[i];
		}
		pos+=4;
		for(i=0;i<len;i++){
			j=i%4;
			packet->data[pos+i]=data[i]^packet->mask_key[j];
		}
	}
	else{
		for(i=0;i<len;i++){
			packet->data[pos+i]=data[i];
		}
	}
	pos+=len;
	return pos;
}

websocket体验:
基于websocket的火拼俄罗斯

ssop太难焊了

最近心血来潮,想做一个用脚踩的键盘,可以让平时使用电脑时把脚也运动起来,然后就做了一块板子。想着玩游戏的时候也可以用脚来控制是多么的激动。

为了省点贴片钱,同时再练习一下焊接技术,拿回来自己贴片,后果还是很不好,我焊了三块板,终于在第三块成功了,但是还是有虚焊,隔一会儿需要用手按一下,这么浪费下来,发现好像浪费的钱都可以贴一片了。。。

不得不承认,ssop太难焊了。

按钮使用的自复位的脚踩开关,踩下时IO口接地,松开时由于IO口自带上拉电阻,端口会复位。

Continue reading “ssop太难焊了”

HTML5浏览器嵌入窗口程序解决方案

浏览器嵌入窗口程序一直以来就是WEB应用程序的首选方案,这种方案只需要实现一个主窗口,并提供一些接口供脚本调用,内部的界面和逻辑处理全部用html,css,javascript去实现。我最早看到的相关应用是四五年前的新浪聊天室。我本人在后来的一些项目中也多次用到这种基于IE内核的实现方式。

随着HTML5的强大,嵌入浏览器方式比嵌入Shockwave Flash的方式更应该作为首选方案。本文介绍嵌入IE,Chrome,Firefox三种方式。

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

1.嵌入IE浏览器

嵌入IE内核应该是早期最常用的方法,使用windows平台上的ActiveX方式,将IWebBrowser2对象嵌入到窗口中,IWebBrowser2接口涉及到很多的接口,可以让我们进行事件处理、操作DOM、与JS通信,使用一个连接点接口与浏览器内部连接,获取和处理事件。

使用IE内核有一个缺点就是用户的操作系统各种各样,内核也是多个版本而且不兼容(只有IE9+才支持HTML5)。导致程序非常不稳定,再有就是不能跨平台。以至于现在嵌入IE应该是最差的方式了。

2.嵌入Firefox

Mozilla的XULRunner是一个跨平台的浏览器应用框架,被Mozilla用于Firefox和ThunderBird等软件的核心,同样是开源和支持HTML5,项目使用XPCOM方式实现,除了XPCOM对象(windows系统的在xpcom.dll中)的获取外,其它属性,对象和函数的访问均与MDN上Javascript的文档相同,可谓文档齐全。同样也有已经实现的第三方C++项目将基于XULRunner的浏览器封装成控件,非常方便使用。

MDN地址:https://developer.mozilla.org/en-US/docs/XULRunner

3.嵌入Chrome

Embedding Chrome:经过本人的研究,个人认为嵌入Chrome是最好的解决方案,Chrome本身开源,高效的v8引擎。同时也有很多附属的开源项目,libcef就是其中一个,cef是chrome embed framework的缩写,意在实现chrome嵌入应用程序,本人对这个项目下载下来后进行过测试,效果非常好,支持HTML5,同时跨平台。

项目地址:http://code.google.com/p/chromiumembedded/

下面是libcef调用的示例程序,给大家做参考。

Continue reading “HTML5浏览器嵌入窗口程序解决方案”

C+Lua实现的HTTP代理服务器

这是一个由C和lua实现的HTTP代理服务器,运行在linux下,服务器使用EPOLL事件模型处理网络流,性能还不错,本人已经使用它代理firefox上网一段时间了,能稳定运行。

如要应用在大并发量的场合,需要在启动程序前设置ulimit为一个合适的值,否则服务器在并发量达到限定值时直接关闭连接,出现连接重置的情况。

代理服务器实现了lua宿主,lua主要用于配置服务器的监听IP和端口,同时处理请求回调,可以通过对请求地址、请求主体内容、请求方式进行判断以决定是否接受该代理。

lua脚本文件名为config.lua,下面是一个示例配置:

--[[
HTTP代理服务器配置文件
@author Hoverlees  http://www.hoverlees.com/blog/?p=1337
]]

--变量名必须为proxy_config
proxy_config={
	--监听IP
	listen="0.0.0.0",
	--监听端口
	port=8766,
	on_request=function(request)
		--[[
		当收到请求后的回调函数 request为一个表格,包含内容:
		1. requestURI  请求地址
		2. requestMethod 请求方式
		3. requestBody 请求体
		4. 请求的HTTP头,如Host,Content-Type,Connection等.
		返回true表示允许代理,返回false表示不允许代理.
		]]
		print("代理:"..request.requestURI)
		return true;
	end
}

从这里下载 HTTP代理服务器 源码

C实现的Sunday Search算法

Sunday Search算法(D.M. Sunday: A Very Fast Substring Search Algorithm. Communications of the ACM, 33, 8, 132-142 (1990))

是大多数情况下比KMP和BM算法更快的串搜索算法,而且原理非常简单易理解.

例如要在”searcqpozreusevnsearch”中搜索”search”

首先初始化一个256长度的索引表,记录每个字节对应搜索串中的倒数位置,即’h’=1,’c’=2,’r’=3,’a’=4,’e’=5,’s’=6,其它字节对应-1

searcqpozreusevnsearch
search

第一次循环发现’q’与’h’不等,这时候查看搜索字符串长度后一位’p’在索引表中的值,发现是-1,则直接右移搜索字符串长度+1

searcqpozreusevnsearch
-------search

第二次循环,’s’与’o’不同,再查看搜索字符串长度后一位’e’在索引表中值为5,直接右移5位

searcqpozreusevnsearch
------------search

第三次循环,’v’与’a’不同,查询索引表中’a’的值为4,右移4位

searcqpozreusevnsearch
----------------search

第四次循环找到匹配.正常情况下比BM和Horspool都要快很多.

以前拿汇编语言写过,由于最近又需要用到,所以又重新拿C语言写了个,这次把它发到博客上方便以后使用.

#include <string.h>
/**
 * Sunday Search算法C实现
 * @author Hoverlees http://www.hoverlees.com
 */
unsigned char* sunday_search(unsigned char* str,int str_len,unsigned char* sub,int sub_len);

Continue reading “C实现的Sunday Search算法”