# stream
// 在node中,流也是一个对象,我们只需要响应流的事件就行了
// data事件:流的数据已经可以读取了(可能会有多次,每次传递chunk是流的一部分数据)
// end事件:流已经到末尾了
// error事件:出错了
'use strict';
var fs = require('fs');
var rs = fs.createReadStream('test.php', 'utf-8');
rs.on('data', function(chunk){
// 异步返回的数据,必须在回调中操作
// 不要用全局变量赋值,可能会是undefined
streamWrite('test1.php', 'utf-8', chunk);
console.log(chunk);
});
rs.on('end', function() {
console.log('over');
});
rs.on('error', function(err) {
console.log(err);
});
function streamWrite(dir, charset, data) {
var ws1 = fs.createWriteStream(dir, charset);
ws1.write(data);
ws1.write('\necho 22');
ws1.end();
}
// 写入二进制流
var ws2 = fs.createWriteStream('2.png');
ws2.write(new Buffer('use stream write bin'), 'utf-8');
ws2.end();
# pipe
// 所有可以读取数据的流都继承自stream.Readable,所有可以写入的流都继承自stream.Writable
// 就像两根水管可以串起来一样,一个Readable和一个Writable也可以串起来
// 所有的数据自动从Readable流进入Writalbe流,这种操作就叫pipe
// Node.js的Readable有一个pipe(),就是用来干这事的
// 下面几行代码实际上就是个复制操作
'use strict';
var fs = require('fs');
var rs = fs.createReadStream('sample.txt');
var ws = fs.createWriteStream('copied.txt');
rs.pipe(ws);
// 默认情况下,当Readable流的数据读取完毕后,end事件就会触发,将自动关闭Writable流
readable.pipe(writable, { end: false }); //传入参数,不让它自动关闭
# http
// http服务器demo,输出hello world
'use strict';
// 导入http模块
var http = require('http');
// 创建http server并传入回调函数
var server = http.createServer(function(request, response){
console.log(request.method + ':' + request.url);
response.writeHead(200, {'Content-Type':'text/html'});
response.end('<h1>hello world</h1>');
});
server.listen(8888);
console.log('server is running in 127.0.0.1:8888');
// 文件服务器 v1.0
'use strict';
// 导入http模块
var http = require('http');
var url = require('url');
var fs = require('fs');
// 创建http server并传入回调函数
var server = http.createServer(function(request, response){
var pathname = url.parse(request.url).pathname;
try {
var data = fs.readFileSync(pathname);
response.writeHead(200, {'Content-Type':'image/x-png'});
response.end(data);
} catch(e) {
console.log(e);
}
response.writeHead(404, {'Content-Type':'text/html'});
response.end('not found');
});
server.listen(8888);
console.log('server is running in 127.0.0.1:8888');
// url.parse
console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));
Url {
protocol: 'http:',
slashes: true,
auth: 'user:pass',
host: 'host.com:8080',
port: '8080',
hostname: 'host.com',
hash: '#hash',
search: '?query=string',
query: 'query=string',
pathname: '/path/to/file',
path: '/path/to/file?query=string',
href: 'http://user:pass@host.com:8080/path/to/file?query=string#hash'
}
// 本地文件处理 可以用path模块(兼容不同操作系统的/)
'use strict';
var path = require('path');
// 解析当前目录 D:\wnmp\www\public\js
var workDir = path.resolve('.');
// D:\wnmp\www\public\js\pub\test\index.php
var filePath = path.join(workDir, 'pub', 'test', 'index.php');
// 文件服务器 v1.1
'use strict';
var fs = require('fs');
var path = require('path');
var http = require('http');
var url = require('url');
// 启动脚本时传入根目录
var rootPath = path.resolve(process.argv[2] || '.');
var server = http.createServer(function(request, response) {
var filePath = path.join(rootPath, url.parse(request.url).pathname);
fs.stat(filePath, function(err, stat) {
if (!err && stat.isFile()) {
response.writeHead(200);
fs.createReadStream(filePath).pipe(response);
} else {
response.writeHead(404);
response.end('not found');
}
});
});
server.listen(8888);
# crypto
// MD5等
'use strict';
const crypto = require('crypto');
// 可以传入md5 sha1 sha256 sha512...
const hash = crypto.createHash('md5');
hash.update('123456');
// 以16进制字符串表示签名(通常是hex和base64格式)
console.log(hash.digest('hex')); //e10adc3949ba59abbe56e057f20f883e
// Hmac也是一种hash算法,可以利用MD5等,需要一个密钥
'use strict';
const crypto = require('crypto');
const hmac = crypto.createHmac('sha256', 'your sign key');
hmac.update('123456');
// 91e953f62f88a32a293a6ee8bd470a69ae77e4bb5549b1e43bd9bcf40f2e3ac3
console.log(hmac.digest('hex'));
// AES对称加密
'use strict';
const crypto = require('crypto');
function aesEncrypt(data, key) {
const cipher = crypto.createCipher('aes192', key);
var crypted = cipher.update(data, 'utf8', 'hex');
crypted += cipher.final('hex');
return crypted;
}
function aesDecrypt(data, key) {
const decipher = crypto.createDecipher('aes192', key);
var decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
var data = 'Hello, this is a secret message!';
var key = 'Password!';
var encrypted = aesEncrypt(data, key);
var decrypted = aesDecrypt(encrypted, key);
console.log('Plain text: ' + data);
console.log('Encrypted text: ' + encrypted);
console.log('Decrypted text: ' + decrypted);
/*
Diffie-Hellman
DH算法是一种密钥交换协议,它可以让双方在不泄漏密钥的情况下协商出一个密钥来
DH算法基于数学原理,比如小明和小红想要协商一个密钥,可以这么做
小明先选一个素数p=23(p必须是素数,否则可能被整除)和一个底数g=5(底数可以任选)和一个秘密整数a=6
A = g^a % p = 8 (5的6次方模23=8) 然后告诉小红 p=23 g=5 A=8
小红根据pgA,也选一个秘密整数b=15 算出:B = g^b % p = 19 然后把B告诉小明
小明算出 s = B^a % p =2 小红算出 s = A^b % p = 2
所以最终协商的密钥 s = 2
第三方只能知道p=23,g=5,A=8,B=19,不知道双方的秘密整数a=6和b=15,所以无法计算出密钥2
*/
'use strict';
const crypto = require('crypto');
// 根据给定的位长度,创建小明的DiffieHellman对象
var ming = crypto.createDiffieHellman(512);
// 生成密钥和公钥(底数和秘密整数)
var ming_keys = ming.generateKeys();
// 返回质数
var prime = ming.getPrime();
// 返回生成器
var generator = ming.getGenerator();
// 根据小明的质数和生成器创建小红的DiffieHellman对象
var hong = crypto.createDiffieHellman(prime, generator);
// 生成密钥和公钥(底数和秘密整数)
var hong_keys = hong.generateKeys();
// 分别算出小明、小红的协商密钥s
var ming_secret = ming.computeSecret(hong_keys);
var hong_secret = hong.computeSecret(ming_keys);
// 生成的密钥是一个Buffer,转成16进制字符串后应该是相等的
console.log(ming_secret.toString('hex') === hong_secret.toString('hex'));
// crypto模块也可以处理数字证书、RSA等