Node.js是一套用来编写高性能网络服务器的JavaScript工具包,一系列的变化由此开始。比较独特的是,Node.js会假设你是在POSIX环境下运行它Linux 或 Mac OS X。如果你是在Windows下,那就需要安装MinGW以获得一个仿POSIX的环境。在Node中,Http是首要的。Node为创建http服务器作了优化,所以你在网上看到的大部分示例和库都是集中在web上(http框架、模板库等)
软件首页:http://nodejs.org
读取文件到字符串
?
var fs = require('fs'); var file = fs.readFileSync(path, "utf8"); console.log(file); ?
编写的一个简单的 HTTP 服务器
?
var sys = require(sys),
http = require(http);
server = http.createServer(function (req, res) {
? res.writeHeader(200, {Content-Type: text/plain});
? res.write(Hello World);
? res.close();
})
server.listen(8000);
sys.puts(Server running at a href="http://127.0.0.1:8000/);
?
读取mongoDB并输出json数据
?index.js
var express = require('express');
var app = express.createServer();
var db = require('./tea/db');
db.open({dbName:'comments'});
app.get('/',function(req,res){
db.findOne('comments',{},function(records){
res.send(records);
});
});
app.listen(8001);
/tea/index.js
var tea = exports;
tea.hello = function(){
console.log('hello world');
}
/tea/db.js
var mongo = require('mongodb');
var tea = tea || {};
tea.db = exports;
tea.db.server = '127.0.0.1';
tea.db.port = 27017;
tea.db.db = null;
tea.db.dbName = '';
tea.db.collection = '';
tea.db.open = function(mongoInfo,callback){
this.dbName = mongoInfo.dbName;
if(!this.db) this.db = new mongo.Db(mongoInfo.dbName, new mongo.Server('127.0.0.1', 27017, {}), {});
this.db.open(function(err,db){
this.db = db;
if(callback) callback(db);
});
return this;
};
tea.db.find = function(collection,query,callback,isFindOne){
? ? ? ? this.db.collection(collection, function(err, collection) {
var func = isFindOne ? 'findOne' : 'find';
collection[func](query,function(err,cursor){
if(!isFindOne) {
? ? ? ? ? ? ? ? ? ? ? ? cursor.toArray(function(err,items){?
if(callback) callback(items);
});
}else{
if(callback) callback(cursor);
}
});
});
}
tea.db.findOne = function(collection,query,callback){
this.find(collection,query,callback,1);
}
tea.db.close = function(){
if(tea.db.db) tea.db.db.close();
}
tea.db.hello = function(){
console.log('Hello World');
}
几个常用字符串hash算法的node封装
// hash.js
exports.additive = function (key, prime) {
key = key instanceof Buffer ? key : new Buffer(key);
prime = prime == undefined ? 0xffffffff : prime;
for (var hash = key.length, i = 0; i < key.length; i++) {
hash += key[i];
}
return (hash % prime);
}
?
exports.rotating = function(key) {
key = key instanceof Buffer ? key : new Buffer(key);
for (var hash = key.length, i = 0; i<key.length; ++i) {
hash = (hash << 4) ^ (hash >> 28) ^ key[i];
}
return hash;
}
?
exports.bernstein = function(key, prime) {
key = key instanceof Buffer ? key : new Buffer(key);
prime = prime == undefined ? 0xffffffff : prime;
var hash = 0;
for (i=0; i<key.length; ++i) {
hash = ?(hash << 5 + hash) + key[i];
}
return hash;
}
?
exports.fnv = function (key){
key = key instanceof Buffer ? key : new Buffer(key);
var p = 16777619, hash = 0x811C9DC5;
for(var i=0; i< key.length; i++) {
hash = (hash * p) ^ key[i];
}
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
return hash;
}
?
exports.fnv1a = function (key){
key = key instanceof Buffer ? key : new Buffer(key);
var p = 16777619, hash = 0x811C9DC5;
for(var i=0; i< key.length; i++) {
hash = (hash ^ key[i]) * p;
}
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
return hash;
}
?
Node 下 Http Streaming 的跨浏览器实现
http://cnodejs.org/blog/?p=112
最近考虑把整个前端架构使用http streaming方式实现
对这方面做了一下调研,并在在node上实现了一个简单的原型
顺带提一下,
楼下pengchun同学所提到的node chat使用的是longpoll的模型
和httpstreaming同属与http comet的解决方案.
不过在具体http连接的处理上有所不同
long poll在数据通道每次接收到一个数据包后即关闭连接,并立即重新打开数据通道
http streaming的数据通道始终处于打开状态.
具体的介绍可以看这里?http://en.wikipedia.org/wiki/Comet_(programming)#Streaming
一些细节:
由于ie下在xhr readystate=3时无法取得responseText,
因此在ie下改为通过使用htmlfile控件调用iframe实现
另在输出正式数据前需现输出1k的噪音数据
以解决浏览器的阻塞问题
原型功能设计
pipe.js
var http = require('http'),
fs = require('fs'),
url = require('url'),
page = null;
// static files read & watch
var readFile = function(files) {
var buffers = {};
// sync read
var fread = function(file, cb){
fs.readFile(file, 'binary', function(err, data){
if (err) {
throw err;
}
buffers[file] = new Buffer(data, 'binary');
console.log('load', file)
});
}
// watch changes
var watch = function watch(file) {
fs.watchFile(file, {persistent: true, interval: 100}, function (curr, prev) {
if (curr.mtime.getTime() != prev.mtime.getTime()) {
fread(file);
}
});
}
// run all files
for (var i = 0; i < files.length; i++) {
watch(files[i]);
fread(files[i]);
}
return buffers;
}
// http query
var httpQuery = function(u, cb){
console.log('http begin');
// parse url
var uinfo = url.parse(u);
// create client
var client = http.createClient(uinfo.port ? uinfo.port : 80, uinfo.hostname, false);
var uri = uinfo.pathname + (uinfo.search ? uinfo.search : '');
var req = client.request('GET', uri, {'host': uinfo.hostname});
// send request
req.end();
console.log('http request sent');
?
?
var len = 4096;
var pointer = 0;
var extendFactor = 2;
// response start
req.on('response', function (res) {
if (res.headers['content-length']) {
len = parseInt(res.headers['content-length']);
}
// body init
var body = new Buffer(len);
// chunk recived
res.on('data', function(chunk){
// extends
if (pointer + chunk.length > len) {
len *= extendFactor;
body = body.copy(new Buffer(len), 0, 0);
console.log('proxy extend to', len);
}
// copy chunk to buf
chunk.copy(body, pointer, 0);
// move pointer
pointer += chunk.length;
})
// response end
res.on('end', function() {
cb(body.length > pointer ? body.slice(0, pointer) : body);
console.log('proxy end', pointer);
});
})
}
?
// main server
var server = http.createServer(function (req, res){
// main page
if (req.url == '/') {
res.writeHeader(200);
res.end(page["pipe.html"]);
// time serve
} else if (req.url == '/time') {
res.writeHeader(200);
res.end(new Date().toString());
// iframe recv
} else if (req.url.match(/^\/iframe\//)) {
var clientid = parseInt(req.url.substr(8));
pipeClient.add(clientid, res, pipeClient.iframe);
console.log('iframe connect', clientid);
// ajax recv
} else if (req.url.match(/^\/ajax\//)) {
var clientid = parseInt(req.url.substr(6));
pipeClient.add(clientid, res, pipeClient.ajax);
console.log('ajax connect', clientid);
// request listen
} else if (req.url.match(/^\/req\//)) {
res.writeHeader(200,{
'Cache-Control': 'no-cache, must-revalidate'
});
res.end();
// url parse
var clientid = parseInt(req.url.substr(5, 13));
// get page
httpQuery("http://localhost:8000/time", function (data){
console.log(data.toString());
pipeClient.write(clientid, data);
console.log("write", clientid, data.length);
});
// error pages
} else {
res.writeHeader(404, {"Content-Type" : "text/html"});
res.end();
}
});
?
var pipeClient = {
timeout : 30000,
client : {},
prefix : "<script>s('",
suffix : "');</script>",
iframe : 'iframe',
ajax : 'ajax',
noise : null,
noiseSize : 1024,
page : null,
init : function(){
this.noise = new Buffer(1024);
for (var i = 0; i < this.noiseSize; i++) {
this.noise[i] = 32;
}
this.page = readFile(['iframe.html']);
},
add : function(id, res, type) {
?
if (type == this.ajax) {
res.writeHeader(200, {
'Cache-Control': 'no-cache, must-revalidate'
});
res.write(this.noise);
} else {
res.writeHeader(200, {
"Content-Type" : "multipart/x-mixed-replace",
'Cache-Control': 'no-cache, must-revalidate'
});
res.write(this.page['iframe.html']);
res.write(this.noise);
}
this.client[id] = {
res : res,
type : type,
tm : setTimeout(function(){
pipeClient.close(id);
}, this.timeout)
};
},
close : function (id) {
console.log("client close", id)
this.client[id].res.end();
this.client[id].res = null;
delete this.client[id];
},
write : function (id, data) {
clearTimeout(this.client[id].tm);
this.client[id].tm = setTimeout(function(){
pipeClient.close(id);
}, this.timeout);
this.client[id].res.write(this.format(data, this.client[id].type));
?
},
format : function(data, type) {
// with iframe
if (type == this.iframe) {
var buf = new Buffer(this.prefix.length + data.length + this.suffix.length);
buf.write(this.prefix, 0, 'binary');
data.copy(buf, this.prefix.length, 0);
buf.write(this.suffix, this.prefix.length + data.length);
// with ajax
} else {
var buf = new Buffer(data.length + 8);
// set length
buf.write(data.length.toString(16), 0, 'binary');
// space padding
for (var i = data.length.toString(16).length; i < 8; i++) {
buf[i] = 32;
}
// set data
data.copy(buf, 8, 0);
}
console.log(buf.toString());
return buf;
}
}
pipeClient.init();
?
page = readFile(['pipe.html']);
setTimeout(function(){
server.listen(8000);
}, 500);
pipe.html
<!-- 客户端程序 -->
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="utf-8" />
<link href='http://fonts.googleapis.com/css?family=Droid+Serif' rel='stylesheet' type='text/css'>
<title>Comet Pipe Demo</title>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("jquery", '1.4');
google.setOnLoadCallback(function(){
$(document.body).ready(function(){
?
?
var Comet = function(options) {
// options init
var opt = {
domain : document.domain,
req : '/req',
iframe : '/iframe',
ajax : '/ajax',
timeout : 300,
cb : null,
cl : null,
ajaxFlagLen : 10,
ajaxNoiseLen : 1024
}
for (k in options) {
opt[k] = options[k];
}
// calculate bytes length for string
var blen = function(str) {
var arr = str.match(/[^\x00-\xff]/ig);
return arr == null ? str.length : str.length + arr.length;
}
// some arguments init
var pageid = new Date().getTime();
var type = $.browser.msie ? 'iframe' : 'ajax';
// public props
var me = {
pageid : pageid,
type : type,
recvUrl : opt[type] + '/' + pageid,
reqUrl : opt.req + '/' + pageid + '/' + type,
conn : null,
div : null,
send : function(){
$.get(this.reqUrl);
}
}
// init iframe receiver
if (me.type == 'iframe') {
// create htmlfire
me.conn = new ActiveXObject("htmlfile");
me.conn.open();
// set domain
me.conn.write("<html><script>document.domain = '"+opt.domain+"'</html>");
me.conn.close();
me.div = me.conn.createElement("div");
me.conn.appendChild(me.div);
me.conn.parentWindow.send = function (data) {
opt.cl ? opt.cb.call(opt.cl, data) : opt.cb(data);
};
me.div.innerHTML = "<iframe id='comet' src='" + me.recvUrl + "'></iframe>";
// init ajax receiver
} else {
me.conn = new XMLHttpRequest();
?
me.conn.open("GET", me.recvUrl, true);
var pos = 0;
var chunk = '';
var data = '';
var size = -1;
var noise = 0;
me.conn.onreadystatechange = function(){
if (this.readyState == 3 || this.readyState == 4) {
// chars length
chunk = this.responseText.substr(pos);
pos = this.responseText.length;
if (noise < opt.ajaxNoiseLen) {
noise += chunk.length;
return;
}
// bytes length
if (size < 0) {
font-famil
- javascript ie6兼容的有关问题
- javascript window open在ie中设立不起作用,求解决
- javascript 字符串拼接效率有关问题
- JavaScript 自动生成图片并合并有关问题
- 不走"<script type='text/javascript'>"标签咋回事
- <script type="javascript/text">的有关问题
- 用servlet+jsp+javascript+jdbc做个简单的办公自动化系统流程,该如何解决
- 怎么打开 javascript:SetData(2010,5,10)
- javaScript = == ===区别,该怎么解决
- javascript 怎么验证name=xx.xx的radio表单
- form action 和 javascript 的提交問題解决方法
- javascript,该怎么处理
- javascript,该如何处理
- javascript 选中文字 但是保存样式 标签
- 新人求问,J2EE方向,html,css,javascript,vml要学到什么程度?解决思路
- javascript 请求servlet兑现将函数中定义的变量作为参数
- javascript 不懂,该如何处理
- javascript 不懂解决方法
- JavaScript 大局函数求实例,高分求
- javaScript 里面 如何知道Object 对象的长度
- javascript 函数调用有什么有关问题,请
- javascript 中文本框中数字如何比较
- javascript IE通过,火狐,google浏览器不过解决思路
- javascript rsa加密/java使用Cipher.getInstance("RSA/ECB/PKCS1Padding")解密,该如何处理
- IE javascript start()函数解决方案
- 关于RTMP 播放器(DELPHI C# FLASH JAVASCRIPT)解决思路
- Chrome Javascript Click 事件,该如何解决
- javascript 实出_blank跳转到新标签页有关问题
- 分享上Google Maps Javascript API v3
- javascript 绑定服务器控件 事件,该如何解决