導航:首頁 > 編程語言 > nodejsbyte

nodejsbyte

發布時間:2023-01-14 04:02:15

A. 如何編譯nodejs的二進制模塊

god Buffer類是一個全局的直接處理二進制數據類型。它可以以各種方式構造。 look
sex 純javascript對於Unicode的處理是友好的,而對二進制並不友好。但處理TCP數據流和文件系統,必須要處理位元組流,所以node.js提供一套策略來創建和操作位元組流。 sex
googog 數據儲存在一個Buffer實例中,一個Buffer的大小是固定的,類似於不可變的整數數組。 good
look Buffer與字元串之間的轉換需要指定明確的編碼。 googog
this Buffer支持的編碼: book
yellow 'ascii'編碼,只為7位的ASCII的數據。這個編碼方法非常快! googog
god 'utf8' 編碼,支持Unicode字元。 yellow
yellow 'utf16le' 編碼,小端編碼的Unicode字元。對(u10000 ~ u10FFFF)的支持。 fuck
book 'ucs2' 是 'utf16le' 編碼的別名。 god
look 'base64' 是 Base64字元串編碼。 this
good 'hex' 表示十六進制編碼,每個byte編碼為兩個十六進制字元。 look
sex 一個Buffer對象也可以使用一個類型數組。Buffer對象克隆到一個ArrayBuffer,用作類型數組存儲支持。node.js提供的Buffer和標准類型化數組是兩套不同的系統,所以Buffer和ArrayBuffer的內存不共享。 sex
sex 注意:雖然V8提供了標准化的類型化數組,但node.js自身定義的Buffer提供了更靈活強大的API,在之後的章節會詳細講解兩者的轉換與使用方法。 good

B. nodejs編譯後js文件名前綴

Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行環境。
Node與javaScript的區別在於,javaScript的頂層對象是window,而node是global

//這里使用的var聲明的變數不是全局的,是當前模塊下的,用global聲明的表示是全局的
var s = 100;
global.s = 200;
//這里訪問到的s是var生命的
console.log(s); //100
//這里訪問到的才是全局變數
console.log(global.s); //200
模塊:在node中,文件和模塊是一一對應的,也就是一個文件就是一個模塊;每個模塊都有自己的作用域,我們通過var申明的變數並非全局而是該模塊作用域下的。

(2)mole模塊

1、文件查找

1)首先按照載入的模塊的文件名稱進行查找,如果沒有找到,則會帶上 .js、.json 或 .node 拓展名在載入
2)以 '/' 為前綴的模塊是文件的絕對路徑。 例如,require('/home/marco/foo.js') 會載入 /home/marco/foo.js 文件。
3)以 './' 為前綴的模塊是相對於調用 require() 的文件的。 也就是說,circle.js 必須和 foo.js 在同一目錄下以便於 require('./circle') 找到它。
4)當沒有以 '/'、'./' 或 '../' 開頭來表示文件時,這個模塊必須是一個核心模塊或載入自 node_moles 目錄。
5)如果給定的路徑不存在,則 require() 會拋出一個 code 屬性為 'MODULE_NOT_FOUND' 的 Error。

2、mole 作用域

在一個模塊中通過var定義的變數,其作用域范圍是當前模塊,外部不能夠直接的訪問,如果我們想一個模塊能夠訪問另外一個模塊中定義的變數,可以有一下兩種方式:
1)把變數作為global對象的一個屬性,但這樣的做法是不推薦的
2)使用模塊對象 mole。mole保存提供和當前模塊有關的一些信息。
在這個mole對象中有一個子對象exports對象,我們可以通過這個對象把一個模塊中的局部變數對象進行提供訪問。

//這個方法的返回值,其實就是被載入模塊中的mole.exports
require('./02.js');
3、__dirname:當前模塊的目錄名。

例子,在 /Users/mjr 目錄下運行 node example.js:
console.log(__dirname);
// 輸出: /Users/mjr
console.log(path.dirname(__filename));
// 輸出: /Users/mjr
4、__filename:當前模塊的文件名(處理後的絕對路徑)。當前模塊的目錄名可以使用 __dirname 獲取。

在 /Users/mjr 目錄下運行 node example.js:

console.log(__filename);
// 輸出: /Users/mjr/example.js
console.log(__dirname);
// 輸出: /Users/mjr
(3)process(進程)

process 對象是一個全局變數,提供 Node.js 進程的有關信息以及控制進程。 因為是全局變數,所以無需使用 require()。

1、process.argv

返回進程啟動時的命令行參數。第一個元素是process.execPath。第二個元素是當前執行的JavaScript文件的路徑。剩餘的元素都是額外的命令行參數。

console.log(process.argv);
列印結果:

2、process.execPath返回啟動進程的可執行文件的絕對路徑。

3、process.env 返回用戶的環境信息。

在process.env中可以新增屬性:

process.env.foo = 'bar';
console.log(process.env.foo);
可以通過delete刪除屬性:

delete process.env.foo;
console.log(process.env);
在Windows上,環境變數不區分大小寫

4、process.pid 屬性返回進程的PID。

5、process.platform屬性返回字元串,標識Node.js進程運行其上的操作系統平台。

6、process.title 屬性用於獲取或設置當前進程在 ps 命令中顯示的進程名字

7、process.uptime() 方法返回當前 Node.js 進程運行時間秒長

注意: 該返回值包含秒的分數。 使用 Math.floor() 來得到整秒鍾。

8、process.versions屬性返回一個對象,此對象列出了Node.js和其依賴的版本信息。

process.versions.moles表明了當前ABI版本,此版本會隨著一個C++API變化而增加。 Node.js會拒絕載入模塊,如果這些模塊使用一個不同ABI版本的模塊進行編譯。

9、process對象-輸入輸出流

var a;
var b;
process.stdout.write('請輸入a的值: ');
process.stdin.on('data', (chunk) => {
if (!a) {
a = Number(chunk);
process.stdout.write('請輸入b的值:');
}else{
b = Number(chunk);
process.stdout.write('a+b的值:'+(a+b));
process.exit();
}
});

(4)Buffer緩沖器

Buffer類,一個用於更好的操作二進制數據的類,我們在操作文件或者網路數據的時候,其實操作的就是二進制數據流,Node為我們提供了一個更加方便的去操作這種數據流的類Buffer,他是一個全局的類

1、如何創建使用buffer

Buffer.from(array) 返回一個 Buffer,包含傳入的位元組數組的拷貝。
Buffer.from(arrayBuffer[, byteOffset [, length]]) 返回一個 Buffer,與傳入的 ArrayBuffer 共享內存。
Buffer.from(buffer) 返回一個 Buffer,包含傳入的 Buffer 的內容的拷貝。
Buffer.from(string[, encoding]) 返回一個 Buffer,包含傳入的字元串的拷貝。
Buffer.alloc(size[, fill[, encoding]]) 返回一個指定大小且已初始化的 Buffer。 該方法比 Buffer.allocUnsafe(size) 慢,但能確保新創建的 Buffer 不會包含舊數據。
Buffer.allocUnsafe(size) 與 Buffer.allocUnsafeSlow(size) 返回一個指定大小但未初始化的 Buffer。 因為 Buffer 是未初始化的,可能包含舊數據。

// 創建一個長度為 10、且用 01 填充的 Buffer。
const buf1 = Buffer.alloc(10,1);
// 創建一個長度為 10、且未初始化的 Buffer。
// 這個方法比調用 Buffer.alloc() 更快,但返回的 Buffer 實例可能包含舊數據,因此需要使用 fill() 或 write() 重寫。
const buf2 = Buffer.allocUnsafe(10);
const buf3 = Buffer.from([1, 2, 3]);
const buf4 = Buffer.from('tést');
console.log(buf1); //<Buffer 01 01 01 01 01 01 01 01 01 01>
console.log(buf2); //<Buffer 00 00 00 00 08 00 00 00 07 00>
console.log(buf3); //<Buffer 01 02 03>
console.log(buf4); //<Buffer 74 c3 a9 73 74>
2、Buffer對象提供的toString、JSON的使用

1)buf.toString(encoding,start,end)

var bf = Buffer.from('miaov');
console.log(bf.toString('utf-8',1,4)); //iaov
console.log(bf.toString('utf-8',0,5)); //miaov
console.log(bf.toString('utf-8',0,6)); //miaov
2)buf.write(string,offset,length,encoding)
string 要寫入 buf 的字元串。
offset 開始寫入的偏移量。默認 0,這里指的是buffer對象的起始要寫入的位置。
length 要寫入的位元組數。默認為 buf.length - offset。
encoding string 的字元編碼。默認為 'utf8'。
返回: 已寫入的位元組數。

var str = "miaov hello";
var bf = Buffer.from(str);
var bf2 = Buffer.alloc(8);
//從0開始寫入5個
bf2.write(str,0,5);
console.log(bf);
console.log(bf2);
3)buf.toJSON()

const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);

console.log(json);
// 輸出: {"type":"Buffer","data":[1,2,3,4,5]}
3、Buffer中靜態方法的使用

1)Buffer.isEncoding(encoding) : 判斷是否是Buffer支持的字元編碼,是則返回true,不是則返回false

console.log(Buffer.isEncoding('utf-8')); //true
2)Buffer.isBuffer(obj) :如果 obj 是一個 Buffer,則返回 true,否則返回 false。

(5)fs(文件系統)

該模塊是核心模塊,需要使用require('fs')導入後使用,該模塊主要用來操作文件

1、fs.open(path, flags, mode, callback)
path:要打開的文件的路徑;
flags:打開文件的方式 讀/寫;
mode:設置文件的模式 讀/寫/執行
callback(err,fd):文件打開以後,在回調函數中做相應的處理,回調函數的兩個參數:
err:文件打開失敗的錯誤保存在err裡面,如果成功err為null
fd:被打開文件的標識

var fs = require('fs');
fs.open('./test.txt','r',function(err,fd){
if(err){
console.log("文件打開失敗");
}else{
console.log("文件打開成功");
}
});

2、fs.openSync(path, flags, mode) :返迴文件描述符。

var fs = require('fs');
console.log(fs.openSync('./test.txt','r')); //3
3、fs.read(fd, buffer, offset, length, position, callback)
從 fd 指定的文件中讀取數據;
buffer 指定要寫入數據的 buffer;
offset 指定 buffer 中開始寫入的偏移量;
length 指定要讀取的位元組數;
position 指定文件中開始讀取的偏移量。 如果 position 為 null,則從文件的當前位置開始讀取;
callback 有三個參數 (err, bytesRead, buffer)

示例:test.txt 中的值為123456789

fs.open('./test.txt','r',function(err,fd){
if(!err){
var bf = Buffer.alloc(5);
fs.read(fd,bf,0,5,0,function(){
console.log(bf.toString()); //12345
})
}
});
4、fs.write(fd, buffer, offset, length, position, callback)
將 buffer 寫入到 fd 指定的文件。
offset 指定 buffer 中要開始被寫入的偏移量,length 指定要寫入的位元組數。
position 指定文件中要開始寫入的偏移量。 如果 typeof position !== 'number',則從當前位置開始寫入。
callback 有三個參數 (err, bytesWritten, buffer),其中 bytesWritten 指定 buffer 中已寫入文件的位元組數。

var fs = require('fs');

fs.open('./test.txt','r+',function(err,fd){
if(!err){
var bf = Buffer.alloc(5);
fs.read(fd,bf,0,5,0,function(){
console.log(bf.toString()); //12345
});
var bf = Buffer.from('test數據');
fs.write(fd,bf,0,10,0);
fs.write(fd,'測試數據2',10,'utf-8');

}
});
fs.write(fd, string, position, encoding, callback)
將 string 寫入到 fd 指定的文件。 如果 string 不是一個字元串,則會強制轉換成字元串。
position 指定文件中要開始寫入的偏移量。 如果 typeof position !== 'number',則從當前位置開始寫入。
encoding 指定字元串的編碼。
callback 有三個參數 (err, written, string),其中 written 指定字元串中已寫入文件的位元組數。 寫入的位元組數與字元串的字元數是不同的。

5、fs.exists(path,callback)檢查指定路徑的文件或者目錄是否存在
fs.appendFile(path, data, callback):將數據追加到文件,如果文件不存在則創建文件。

//檢查文件是否存在
var fs = require('fs');
var filename = './test2.txt';
fs.exists(filename,function(isExists){
if(!isExists){
fs.writeFile(filename,'miaov',function(err){
if(err){
console.log("文件創建失敗");
}else{
console.log("文件創建成功");
}
});
}else{
fs.appendFile(filename,'-leo',function(err){
if(err){
console.log("文件內容追加失敗");
}else{
console.log("文件內容追加成功");
}
})
}
});
(6)前端項目自動化構建

1、創建myProject項目文件以及對應的文件夾

var projectData ={
'name':'myProject',
'fileData':[
{
'name':'css',
'type':'dir'
},{
'name':'js',
'type':'dir'
},{
'name':'images',
'type':'dir'
},{
'name':'index.html',
'type':'file',
'content' : '<html>\n\t<head>\n\t\t<title>title</title>\n\t</head>\n\t<body>\n\t\t<h1>Hello</h1>\n\t</body>\n</html>'
}
]
};

var fs = require('fs');

if(projectData.name){
// 創建項目文件夾
fs.mkdirSync(projectData.name);
var fileData = projectData.fileData;
if(fileData && fileData.length){
fileData.forEach(function(file){
//文件或文件夾路徑
file.path = './'+projectData.name +'/'+ file.name;
//根據type類型創建文件或文件夾
file.content = file.content || '';

switch(file.type){
case 'dir':
fs.mkdirSync(file.path);
break;

case 'file':
fs.writeFileSync(file.path,file.content);
break;
default:
break;
}

});
}

}
2、自動打包多個文件

var fs = require('fs');
var filedir = './myProject/dist';

fs.exists(filedir,function(isExists){
if(!isExists){
fs.mkdirSync(filedir);
}
fs.watch(filedir,function(ev,file){
//只要有一個文件發生了變化,我們就需要對文件夾下的所有文件進行讀取、合並
fs.readdir(filedir,function(err,dataList){
var arr = [];
dataList.forEach(function(file){
if(file){
//statSync查看文件屬性
var info = fs.statSync(filedir + '/' +file);
//mode文件許可權
if(info.mode === 33206){
arr.push(filedir + '/' +file);
}
}
});
//讀取數組中的文件內容
var content = '';
arr.forEach(function(file){
var c = fs.readFileSync(file);
content += c.toString()+'\n';
});
//合並文件中的內容
fs.writeFileSync('./myProject/js/index.js',content);

})

});
});

(7)使用node進行web開發

1、搭建一個http的伺服器,用於處理用戶發送的http請求

//載入一個http模塊
var http = require('http');
//通過http模塊下的createServer創建並返回一個web伺服器對象
var server = http.createServer();
//開啟 HTTP 伺服器監聽連接,只有調用了listen方法以後,伺服器才開始工作
server.listen(8000,'localhost');
//伺服器是否正在監聽連接
server.on('listening',function(){
console.log("listening..........");
});
//每次接收到一個請求時觸發,每個連接可能有多個請求(在 HTTP keep-alive 連接的情況下)。
server.on('request',function(){
res.write('<p>hello</p>');
res.end();
});
2、request方法有兩個參數:request、response

1)request:http.IncomingMessage的一個實例,獲取請求的一些信息,如頭信息,數據等
httpVession:使用的http協議的版本
headers:請求頭信息中的數據
url:請求的地址
method:請求的方式

2)response:http.ServerResponse的一個實例,可以向請求的客戶端輸出返回響應
write(chunk,encoding):發送一個數據塊到相應正文中
end(chunk,encoding):當所有的正文和頭信息發送完成以後調用該方法告訴伺服器數據已經全部發送完成了,這個方法在每次完成信息發送以後必須調用,並且是最後調用。
statusCode:該屬性用來設置返回的狀態碼
setHeader(name,value):設置返回頭信息
writeHead(statusCode,reasonPhrase,headers)這個方法只能在當前請求中使用一次,並且必須在response.end()之前調用

3、使用fs模塊實現行為表現分離

var http = require('http');
var url = require('url');
var fs = require('fs');

var server = http.createServer();
//html文件的路徑
var htmlDir = __dirname + '/html/';
server.on('request',function(request,response){
var urlStr = url.parse(request.url);
//根據pathname匹配對應的html文件
switch(urlStr.pathname){
case '/':
sendData(htmlDir + 'index.html',request,response);
break;
case '/user':
sendData(htmlDir + 'user.html',request,response);
break;
case '/login':
sendData(htmlDir + 'login.html',request,response);
break;
default:
//處理其他情況
sendData(htmlDir + 'err.html',request,response );
break;
}
});

function sendData(file,request,response){
//讀取文件,存在則返回對應讀取的內容,不存在則返回錯誤信息
fs.readFile(file,function(err,data){
if(err){
response.writeHead(404,{
'content-type':'text/html;charset=utf-8'
});
response.end('<h1>頁面不存在</h1>')
}else{
response.writeHead(200,{
'content-type':'text/html;charset=utf-8'
});
response.end(data);
}
})
}
server.listen(8000,'localhost');

C. nodejs socket怎麼主動刷新緩存區數據

清空socket緩存區的數據的方法
由於socket是以數據流的形式發送數據,接收方不知道對方一次性發送了多少數據,也能保證對方一次性發送的數據能在同一刻接收到,所以Receive方法是這么工作的:
接受一個byye[]類型的參數作為緩沖區,在經過一定的時間後把接收到的數據填充到這個緩沖區裡面,並且返回實際接收到數據的長度,這個實際接收到的數據長度有可能為0(沒有接收到數據)、大於0小於緩沖區的長度(接收到數據,但是沒有我們預期的多)、等於緩沖區的長度(說明接收到的數據大於等於我們預期的長度)。
每次接收緩沖區都用同一個byte[] byteMessage,並且你沒有檢查接收到的數據長度,所以第一次你接收到的數據是123456,第二次你只接收到了8,但是緩沖區裡面還有23456,所以加起來就是823456了。
socket接收緩沖區的大小有講究,設置大了接收起來慢,因為它要等盡可能多的數據接收到了再返回;設置小了需要重復多次調用接收方法才能把數據接收完,socket有個屬性,標識了系統默認的接收緩沖區大小,可以參考這個!
還有就是用recv讀取,但是由於不知道緩存里有多少數據,如果是阻塞模式,到最後必然等到超時才知道數據已經讀取完畢,這是個問題。
另一個是用fgetc,通過返回判斷是否是feof:
whlie (1) { a=fgetc(f);if (feof(f)) break;//…
b=fgetc(f);if (feof(f)) break;//…}當然,我不知道讀取完畢後最後一次調用fgetc會不會堵塞,需要測試。
在非阻塞模式下,我們用recv就可以輕松搞定了,但是阻塞模式下,由於我們不知道緩沖區有多少數據,不能直接調用recv嘗試清除。
使用一個小小的技巧,利用select函數,我們可以輕松搞定這個問題:
select函數用於監視一個文件描述符集合,如果集合中的描述符沒有變化,則一直阻塞在這里,直到超時時間到達;在超時時間內,一旦某個描述符觸發了你所關心的事件,select立即返回,通過檢索文件描述符集合處理相應事件;select函數出錯則返回小於零的值,如果有事件觸發,則返回觸發事件的描述符個數;如果超時,返回0,即沒有數據可讀。
重點在於:我們可以用select的超時特性,將超時時間設置為0,通過檢測select的返回值,就可以判斷緩沖是否被清空。通過這個技巧,使一個阻塞的socket成了『非阻塞』socket.
現在就可以得出解決方案了:使用select函數來監視要清空的socket描述符,並把超時時間設置為0,每次讀取一個位元組然後丟棄(或者按照業務需要進行處理,隨你便了),一旦select返回0,說明緩沖區沒數據了(「超時」了)。

D. 誰能將這段nodejs代碼翻譯成java代碼

Stringsk="xxx";
KeyGeneratorgenerator=KeyGenerator.getInstance(「HmacSHA256」);
SecretKeykey=generator.generateKey();
Macmac=Mac.getInstance(key.getAlgorithm());
mac.init(key);
byte[]bytes=mac.doFinal(str.getBytes());

StringBuffersb=newStringBuffer();
for(inti=0;i<bytes.length;i++){
intt=bytes[i];
sb.append(Integer.toString(t>>4&0xF,16)).append(
Integer.toString(t&0xF,16));
}
Stringsignature=sb.toString();

E. 求教nodejs怎麼對密碼進行加鹽的hash加密

nodejs怎麼對密碼進行加鹽的hash加密?

以前java項目最近打算用node.js重寫,但是加密這里實在沒搞定。java中加密是:1024次加鹽sha-1加密,
一個例子:salt:47998d63768aa877,密文:,明文:yunstudio2013
下面是java代碼:
private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
try {
MessageDigest digest = MessageDigest.getInstance(algorithm);
if (salt != null) {
digest.update(salt);
}
byte[] result = digest.digest(input);
for (int i = 1; i < iterations; i++) {
digest.reset();
result = digest.digest(result);
}
return result;
} catch (GeneralSecurityException e) {
throw Exceptions.unchecked(e);
}
}
我在js裡面是這么乾的,但是結果一直不對,代碼如下:
//
var hash = crypto.createHmac("sha1", 「47998d63768aa877」).update(「yunstudio2013」).digest(「hex」);
for (var i = 1; i < 1024; i++) {
hash = crypto.createHmac("sha1", 「47998d63768aa877」).update(hash).digest(「hex」);
console.log(hash);
}

F. 位元組跳動轉用nodejs

是。根據查詢位元組跳動軟體消息顯示,轉用是nodejs。Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行環境。 Node.js 使用了一個事件驅動、非阻塞式 I/O 的模型。

G. 下面的java 加密用nodejs該怎麼實現謝謝

說說個人的看法,僅供參考。
我們可以把java的介面進一步封裝成一個服務,例如rest風格的介面,然後nodejs進行調用,數據封裝使用Json,也是一種解決思路。

H. 如何使用 NodeJS 將文件或圖像上傳到伺服器

下面先介紹上傳文件到伺服器(多文件上傳):
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;
import org.apache.commons.fileupload.*;

public class upload extends HttpServlet {
private static final String CONTENT_TYPE = "text/html; charset=GB2312";
//Process the HTTP Post request
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out=response.getWriter();
try {
DiskFileUpload fu = new DiskFileUpload();
// 設置允許用戶上傳文件大小,單位:位元組,這里設為2m
fu.setSizeMax(2*1024*1024);
// 設置最多隻允許在內存中存儲的數據,單位:位元組
fu.setSizeThreshold(4096);
// 設置一旦文件大小超過getSizeThreshold()的值時數據存放在硬碟的目錄
fu.setRepositoryPath("c://windows//temp");
//開始讀取上傳信息
List fileItems = fu.parseRequest(request);
// 依次處理每個上傳的文件
Iterator iter = fileItems.iterator();
//正則匹配,過濾路徑取文件名
String regExp=".+////(.+)$";
//過濾掉的文件類型
String[] errorType={".exe",".com",".cgi",".asp"};
Pattern p = Pattern.compile(regExp);
while (iter.hasNext()) {
FileItem item = (FileItem)iter.next();
//忽略其他不是文件域的所有表單信息
if (!item.isFormField()) {
String name = item.getName();
long size = item.getSize();
if((name==null||name.equals("")) && size==0)
continue;
Matcher m = p.matcher(name);
boolean result = m.find();
if (result){
for (int temp=0;temp<ERRORTYPE.LENGTH;TEMP++){
if (m.group(1).endsWith(errorType[temp])){
throw new IOException(name+": wrong type");
}
}
try{
//保存上傳的文件到指定的目錄
//在下文中上傳文件至資料庫時,將對這里改寫
item.write(new File("d://" + m.group(1)));
out.print(name+" "+size+"");
}
catch(Exception e){
out.println(e);
}
}
else
{
throw new IOException("fail to upload");
}
}
}
}
catch (IOException e){
out.println(e);
}
catch (FileUploadException e){
out.println(e);
}

}
}
現在介紹上傳文件到伺服器,下面只寫出相關代碼:
以sql2000為例,表結構如下:
欄位名:name filecode
類型: varchar image
資料庫插入代碼為:PreparedStatement pstmt=conn.prepareStatement("insert into test values(?,?)");
代碼如下:
。。。。。。
try{
這段代碼如果不去掉,將一同寫入到伺服器中
//item.write(new File("d://" + m.group(1)));

int byteread=0;
//讀取輸入流,也就是上傳的文件內容
InputStream inStream=item.getInputStream();
pstmt.setString(1,m.group(1));
pstmt.setBinaryStream(2,inStream,(int)size);
pstmt.executeUpdate();
inStream.close();
out.println(name+" "+size+" ");
}
。。。。。。
這樣就實現了上傳文件至資料庫

I. nodejs 承載 多少 websocket

首先是協議的升級,這個比較簡單,就簡述一下:當在客戶端執行new
Websocket("ws://XXX.com/")的時候,客戶端就會發起請求報文進行握手申請,報文中有個很重要的key就是Sec-
WebSocket-Key,服務端獲取到key,然後將這個key與字元串258EAFA5-E914-47DA-95CA-C5AB0DC85B11
相連,對新的字元串通過sha1安全散列演算法計算出結果後,再進行base64編碼,並且將結果放在請求頭的"Sec-WebSocket-
Accept"中返回即可完成握手。具體請看代碼:
server.on('upgrade', function (req, socket, upgradeHead) {
var key = req.headers['sec-websocket-key'];
key = crypto.createHash("sha1").update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest("base64");
var headers = [
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
'Sec-WebSocket-Accept: ' + key
];
socket.setNoDelay(true);
socket.write(headers.join("\r\n") + "\r\n\r\n", 'ascii');
var ws = new WebSocket(socket);
webSocketCollector.push(ws);
callback(ws);
});

upgrade事件其實是http這個模塊的封裝,再往底層就是net模塊的實現,其實都差不多,如果直接用net模塊來實現的話,就是監聽net.createServer返回的server對象的data事件,接收到的第一份數據就是客戶端發來的升級請求報文。

上面那段代碼就完成了websocket的握手,然後就可以開始數據傳輸了。

看數據傳輸之前,先看看websocket數據幀的定義(因為覺得深入淺出nodejs里的幀定義圖最容易理解,所以就貼這張了):

上面的圖中,每一列就是一個位元組,一個位元組總共是8位,每一位就是一個二進制數,不同位的值會對應不同的意義。

fin:指示這個是消息的最後片段。第一個片段可能也是最後的片段。如果為1即為最後片段,(其實這個位的用途我個人有點疑惑,按照書上以及網上查的資
料,當數據被分片的時候,不同片應該都會有fin位,會根據fin為是不是0來判斷是否為最後一幀,但是實際實現中卻發現,當數據比較大需要分片時,服務
端收到的數據就只有第一幀是有fin位為1,其他幀則整個幀都是數據段,也就是說,感覺這個fin位似乎用不上,至少我自己寫的demo中是通過數據長度
來判斷是否到了最後一幀,完全沒用到這個fin位是否為1來判斷)

rsv1、rsv2、rsv3:各佔一個位,用於擴展協商,基本上不怎麼需要理,一般都是0

opcode:佔四個位,可以表示0~15的十進制,0表示為附加數據幀,1表示為文本數據幀,2表示二進制數據幀,8表示發送一個連接關閉的數據幀,9
表示ping,10表示pong,ping和pong都是用於心跳檢測,當一端發送ping時,另一端必須響應pong表示自己仍處於響應狀態。

masked:佔一個位,表示是否進行掩碼處理,客戶端發送給服務端時為1,服務端發送給客戶端時為0

payload
length:佔7位,或者7+16位、或者7+64位。如果第二個位元組的後面七個位的十進制值小於或等於125,則直接用這七個位表示數據長度;如果該
值為126,說明
125<數據長度<65535(16個位能描述的最大值,也就是16個1的時候),就用第三個位元組及第四個位元組即16個位來表示;如果該值為
127,則說明數據長度已經大於65535,16個位也已經不足以描述數據長度了,就用第三到第十個位元組這八個位元組來描述數據長度。

masking key:當masked為1的時候才存在,用於對我們需要的數據進行解密。

payload data:我們需要的數據,如果masked為1,該數據會被加密,要通過masking key進行異或運算解密才能獲取到真實數據。

幀定義解釋完了,就可以根據數據來進行解析了,當有data過來的時候,先獲取需要的數據信息,下面這段代碼將獲取到數據在data里的位置,以及數據長度,masking key以及opcode:
WebSocket.prototype.handleDataStat = function (data) {
if (!this.stat) {
var dataIndex = 2; //數據索引,因為第一個位元組和第二個位元組肯定不為數據,所以初始值為2
var secondByte = data[1]; //代表masked位和可能是payloadLength位的第二個位元組
var hasMask = secondByte >= 128; //如果大於或等於128,說明masked位為1
secondByte -= hasMask ? 128 : 0; //如果有掩碼,需要將掩碼那一位去掉
var dataLength, maskedData;
//如果為126,則後面16位長的數據為數據長度,如果為127,則後面64位長的數據為數據長度
if (secondByte == 126) {
dataIndex += 2;
dataLength = data.readUInt16BE(2);
} else if (secondByte == 127) {
dataIndex += 8;
dataLength = data.readUInt32BE(2) + data.readUInt32BE(6);
} else {
dataLength = secondByte;
}
//如果有掩碼,則獲取32位的二進制masking key,同時更新index
if (hasMask) {
maskedData = data.slice(dataIndex, dataIndex + 4);
dataIndex += 4;
}
//數據量最大為10kb
if (dataLength > 10240) {
this.send("Warning : data limit 10kb");
} else {
//計算到此處時,dataIndex為數據位的起始位置,dataLength為數據長度,maskedData為二進制的解密數據
this.stat = {
index: dataIndex,
totalLength: dataLength,
length: dataLength,
maskedData: maskedData,
opcode: parseInt(data[0].toString(16).split("")[1] , 16) //獲取第一個位元組的opcode位
};
}
} else {
this.stat.index = 0;
}
};

代碼中均有注釋,理解起來應該不難,直接看下一步,獲取到數據信息後,就要對數據進行實際解析了:

經過上面handleDataStat方法的處理,stat中已經有了data的相關數據,先判斷opcode,如果為9說明是客戶端發起的
ping心跳檢測,直接返回pong響應,如果為10則為服務端發起的心跳檢測。如果有masking
key,則遍歷數據段,對每個位元組都與masking
key的位元組進行異或運算(網上看到一個說法很形象:就是輪流發生X關系),^符號就是進行異或運算啦。如果沒有masking
key則直接通過slice方法把數據截取下來。

獲取到數據後,放進datas里保存,因為有可能數據被分片了,所以再將stat里的長度減去當前數據長度,只有當stat里的長度為0的時候,
說明當前幀為最後一幀,然後通過Buffer.concat將所有數據合並,此時再判斷一下opcode,如果opcode為8,則說明客戶端發起了一個
關閉請求,而我們獲取到的數據則是關閉原因。如果不為8,則這數據就是我們需要的數據。然後再將stat重置為null,datas數組置空即可。至此,
我們的數據解析就完成了。
WebSocket.prototype.dataHandle = function (data) {
this.handleDataStat(data);
var stat;
if (!(stat = this.stat)) return;
//如果opcode為9,則發送pong響應,如果opcode為10則置pingtimes為0
if (stat.opcode === 9 || stat.opcode === 10) {
(stat.opcode === 9) ? (this.sendPong()) : (this.pingTimes = 0);
this.reset();
return;
}
var result;
if (stat.maskedData) {
result = new Buffer(data.length-stat.index);
for (var i = stat.index, j = 0; i < data.length; i++, j++) {
//對每個位元組進行異或運算,masked是4個位元組,所以%4,藉此循環
result[j] = data[i] ^ stat.maskedData[j % 4];
}
} else {
result = data.slice(stat.index, data.length);
}
this.datas.push(result);
stat.length -= (data.length - stat.index);
//當長度為0,說明當前幀為最後幀
if (stat.length == 0) {
var buf = Buffer.concat(this.datas, stat.totalLength);
if (stat.opcode == 8) {
this.close(buf.toString());
} else {
this.emit("message", buf.toString());
}
this.reset();
}
};

完成了客戶端發來的數據解析,還需要一個服務端發數據至客戶端的方法,也就是按照上面所說的幀定義來組裝數據並且發送出去。下面的代碼中基本上每一行都有注釋,應該還是比較容易理解的。
//數據發送
WebSocket.prototype.send = function (message) {
if(this.state !== "OPEN") return;
message = String(message);
var length = Buffer.byteLength(message);
// 數據的起始位置,如果數據長度16位也無法描述,則用64位,即8位元組,如果16位能描述則用2位元組,否則用第二個位元組描述
var index = 2 + (length > 65535 ? 8 : (length > 125 ? 2 : 0));
// 定義buffer,長度為描述位元組長度 + message長度
var buffer = new Buffer(index + length);
// 第一個位元組,fin位為1,opcode為1
buffer[0] = 129;
// 因為是由服務端發至客戶端,所以無需masked掩碼
if (length > 65535) {
buffer[1] = 127;
// 長度超過65535的則由8個位元組表示,因為4個位元組能表達的長度為4294967295,已經完全夠用,因此直接將前面4個位元組置0
buffer.writeUInt32BE(0, 2);
buffer.writeUInt32BE(length, 6);
} else if (length > 125) {
buffer[1] = 126;
// 長度超過125的話就由2個位元組表示
buffer.writeUInt16BE(length, 2);
} else {
buffer[1] = length;
}
// 寫入正文
buffer.write(message, index);
this.socket.write(buffer);
};

最後還要實現一個功能,就是心跳檢測:防止服務端長時間不與客戶端交互而導致客戶端關閉連接,所以每隔十秒都會發送一次ping進行心跳檢測
//每隔10秒進行一次心跳檢測,若連續發出三次心跳卻沒收到響應則關閉socket
WebSocket.prototype.checkHeartBeat = function () {
var that = this;
setTimeout(function () {
if (that.state !== "OPEN") return;
if (that.pingTimes >= 3) {
that.close("time out");
return;
}
//記錄心跳次數
that.pingTimes++;
that.sendPing();
that.checkHeartBeat();
}, 10000);
};
WebSocket.prototype.sendPing = function () {
this.socket.write(new Buffer(['0x89', '0x0']))
};
WebSocket.prototype.sendPong = function () {
this.socket.write(new Buffer(['0x8A', '0x0']))
};

至此,整個websocket的實現就完成了,此demo只是大概實現了一下websocket而已,在安全之類方面肯定還是有很多問題,若是真正生產環境中還是用socket.io這類成熟的插件比較好。不過這還是很值得一學的。

J. 使用Nodejs部署智能合約

實現智能合約的方式很多種,可以用truffle框架來實現,編譯,部署。
這里介紹一種簡單的使用nodejs來實現,編譯,部署的方法。
創建一個nodejs項目,實現一個簡單的智能合約。

這個合約實現了一個造幣和轉幣的邏輯。
我們的合約是運行在evm上面的位元組碼,solidity是靜態語言,需要通過編譯器生成evm的位元組碼。

調用 node compile.js ,對BaseToken進行編譯,生成位元組碼。web3中提供了一個部署合約的介面,使用如下,

利用編譯生成的abi和bytecode,創建一個合約對象,然後進行發布,等待著非同步執行的方法輸出合約地址 contractAddress ,這樣就完成了部署。不過這種方式有一個問題,就是在發布合約時,你的私鑰處於聯網狀態,
處於安全策略,我們需要盡量避免私鑰在聯網狀態。

以太坊上部署合約是向空地址發送一個附有位元組碼的簽名交易,其中發送者就是這個合約的擁有者。因此我們只需要將合約構建成一筆交易,我們在無網狀態下對這筆交易進行簽名,然後將簽名發送到以太坊網路中。這樣能夠降低我們私鑰被泄漏的風險。
對合約的簽名方法如下:

以上對一個合約簽名,這里需要注意的問題是,to的地址需要是,空地址。
完成簽名之後,我們把這筆交易發送出去就好,最簡單的方法就是使用 etherscan的發送Tx的方式 ,一旦發送完成,部署完成,就可以看到合約地址。

閱讀全文

與nodejsbyte相關的資料

熱點內容
微信直接加為好友 瀏覽:467
可以用微信傳送的文件app 瀏覽:294
pdf文件解析亂碼 瀏覽:479
光照無關圖代碼 瀏覽:688
Linux讀寫文件前八位 瀏覽:597
word如何繪制餅狀圖 瀏覽:172
w7系統搜索文件夾 瀏覽:618
java線程變數 瀏覽:854
蘋果電腦word是只讀文件 瀏覽:691
ps5國行備份文件大小 瀏覽:754
linux恢復刪除文件命令 瀏覽:805
win10家庭版打不開qq文件 瀏覽:794
女生來例假有哪個app比較好 瀏覽:66
調用後台介面為什麼不顯示數據 瀏覽:363
js判斷重復 瀏覽:422
聯通如何切換到網路電視 瀏覽:191
學編程的優勢哪裡靠譜 瀏覽:939
溝通文件 瀏覽:267
水準測量平差程序 瀏覽:78
cf如何解決網路誤封 瀏覽:952

友情鏈接