1. nodejs可以接受tcp伺服器的數據嗎
nodejs中我們使用net模塊來創建tcp伺服器,tcp客戶端,實現伺服器與客戶端拍櫻宴之前的數據通信
創建tcp伺服器
var server=net.createServer([optations],[connectionListener])
optations:{allowHalfOpen:boolean}
allowHalfOpen:false 當伺服器接受到客戶端發送的一個FIN包時候,會回發一個FIN包,當為true時伺服器不會回FIN包,使得tcp伺服器可以繼續發送數據到客戶端,但是不會接受客戶端發送的數據,開發者必須調動end方法來關閉socket,默認是false
connectionListener:當客戶端與伺服器連接上了,可以觸發的回襲銀調函數。
function(socket){
//.......
}
我們也可以不用回調函數來寫連接上做什麼處理,連接上會觸發connection事件
var server=net.createServer()返回創建的tcp伺服器
我們可以server.on('connection',function(socket){
})
在創建完tcp伺服器我們通知伺服器要監聽客戶端連接
server.listen(port,[host],[backlog],[callback])
port:監聽的埠,為0時候tcp伺服器分配一個隨機的埠
host:監聽的ip和主機名,省略該參數,伺服器監聽任何ipv4地址的客戶端連接
backlog:指定等待隊列中最大的客戶端連接最大數量 默認511
當指定埠、ip這個時候伺服器開始監聽這個ip這個埠的客戶端了,這個時候觸發listening事件,可以指定callback參數來處理觸發listening具體要做什麼
我們也可以
server.on('lisening',function(){
//.......
})
創建一個tcp伺服器頌毀後可以用server.address()查看tcp伺服器監聽的信息
var address=server.address()
addres是一個對象
prot :監聽的埠
address:監聽的ip
family:ipv4還是ipv6
我們可以使用getConnections()查看與伺服器連接的客戶端的數量
server.getConnections(callback)
callback:function(err,count){
}
err:錯誤信息
count:為連接伺服器的數量
我們也可以設置最大的連接數,超過這個數字,伺服器不允許連接
server.maxConnections=2
伺服器關閉
server.close([callback])
這個 方法讓tcp伺服器拒絕新的客戶端連接,原有已經連上的客戶端是不關閉的,當所有的連接伺服器的客戶端關閉時候,伺服器默認自動關閉,觸發伺服器的close事件
下面我們寫一個tcp伺服器
var net=require("net");
opations={allowHalfOpne:false}
var server=net.createServer(opations);
server.on('connection',function(socket){
server.maxConnections=2;
console.log("伺服器最大連接數為%s",server.maxConnections)
server.getConnections(function(err,count){
console.log("已經有%s個客戶端連接",count)
})
console.log("%s客戶端與伺服器建立連接",server.address().address)
})
server.on('error',function(err){
throw err;
})
server.on('listening',function(){
console.log("伺服器開始監聽%j",server.address())
console.log("伺服器開始監聽")
})
server.listen(9966,'192.168.0.3');
setTimeout(function(){
server.close(function(){
console.log("tcp伺服器關閉11111")
})
console.log("tcp伺服器關閉")
},20000)
注意連接成功的時候觸發的connection事件,執行的方法,參數是一個socket埠對象,這個就是伺服器所監聽的埠對象,所以我們socket.address().address返回給我們的是監聽ip
socket埠對象
port:埠
address:ip
family:ipv4 ipv6
socket埠對象,可以讀取客戶端發送的流數據,每次接收到客戶端發送的數據觸發data事件。
接受客戶端發送的消息(在連接成功的觸發函數中 讓server監聽data事件做相應的處理)
server.on('connection',function(socket){
socket.on('data',function(data){
socket.setEncoding("utf-8");
console.log(data)
//console.log(data.toString())
})
})
bytesRead為socket埠對象監聽客戶端發送的數據位元組數
console.log(socket.bytesRead)
當客戶端關閉時候,觸發socket埠對象的end事件
我們把客戶端連接發送的數據保存到一個文件下
var net=require("net");
var fs=require("fs");
var server =net.createServer();
var op={
flags:"a",
encoding:"utf-8"
}
var file=fs.createWriteStream('./socket.txt',op)
server.on('connection',function(socket){
socket.on('data',function(data){
file.write(data);
})
})
server.on('listening',function(){
console.log("監聽開始")
})
server.listen('1111','192.168.0.3')
以管道形式發送數據到文件
var net=require("net");
var fs=require("fs");
var server =net.createServer();
var op={
flags:"a",
encoding:"utf-8"
}
var file=fs.createWriteStream('./socket.txt',op)
server.on('connection',function(socket){
//socket.on('data',function(data){
// file.write(data);
//})
socket.pipe(file,{end:false});
socket.on("end",function(){
file.end("wanbi")
})
})
server.on('listening',function(){
console.log("監聽開始")
})
server.listen('1111','192.168.0.3')
tcp客戶端
創建tcp客戶端
var client =new net.socket([opations])
optation:fd 一個現有的socket埠對象文件描述
type :ipv4 、ipv6
allowHalfOpne:true、false
連接伺服器
client.connect(prot,[host],[callback])
host不指定默認為本地ip
回調函數表示連接上了做什麼
若沒有可以socket埠對象觸發connect事件
client.on("connect",function(){
})
當我們連接成功後客戶端伺服器端的socket埠對象有下面的屬性
remoteAddress、remotePort、localAddress、localPort
socket埠對象可以寫入伺服器、客戶端流數據
socket.write(data,[encodeing],[callback])
寫入數據少時候我們直接寫入緩存區,數據很多時候,緩存區滿了,我們要把數據寫入緩存隊列中,這個時候write(data) 返回false,觸發drain
我們可以用bufferSize看緩存隊列中有多少個位元組
socket.on("error",function(err){
})
當遇到error時候這個socket埠對象應該銷毀
socket.destory()
socket.end([data],[encoding])
這個方法表示我們要關閉socket埠對象,這個不是關閉伺服器的close方法,後者是關閉伺服器,實現的效果是不能讓客戶端連接了,前者是關閉連接(socket埠對象)
當我們使用伺服器的socket埠對象(連接客戶端得)的end(data,encoding)方法時候,會觸發客戶端socket埠對象end事件
伺服器:
socket.end('88');
客戶端會執行下面的代碼:
client.on("end",function(){
//......
})
伺服器端不會退出應用程序,即使所有的客戶端都斷開了,這個時候我們要server.unref(),退出程序,可以用server.ref()阻止程序退出.
當socket埠對象徹底關閉時候會觸發close事件,我們可以指定當埠對象關閉時候做的處理
socket.on(''close',faction(had_error){
if(had_error){}
else{}
})
socket.writtenBytes表示寫了多少個位元組
我們tcp伺服器與客戶端連接了,但是突然間有一個斷電了,來不及向另一端發送關閉連接的FIN包,這樣另一邊這個socket埠永遠處於連接狀態,我們用socket.setKeepAlive([enable],[inteval])定時向另一端發送監測包,
我們實現一個伺服器讀一個文件的信息,當有客戶單連接上,吧這個信息傳給客戶端,輸出在控制台
伺服器代碼
var net=require("net");
var fs=require("fs");
var server =net.createServer();
var op={
flags:"r",
encoding:"utf-8"
}
var file=fs.createReadStream('./socket.txt',op)
server.on('connection',function(socket){
file.on('data',function(data){
socket.write(data);
})
socket.on("end",function(){
file.end("wanbi")
})
})
server.on('listening',function(){
console.log("監聽開始")
})
server.listen('1111','192.168.0.3')
客戶端代碼
var net=require("net");
var client=new net.Socket();
client.connect(1111,'192.168.0.3')
client.on('connect',function(){
console.log("ok")
})
client.on("data",function(data){
console.log(data.toString())
})
2. 如何啟動一個TCP套接字連接和js寫的東西嗎
你可以創建兩種類型的TCP套接字:1. 服務端,2. 客戶端。服務端TCP監聽來自客戶端的連接請求,並使用TCP連接向客戶端發送數據;客戶端TCP連接到服務端並與伺服器交互數據。客戶端與服務端之間依靠套接字進行雙向通信。
在NodeJS中使用TCP需要引用net模塊。net模塊是NodeJS中非同步網路編程的封裝,可以做很多事情,本文僅關注於如何使用該模塊創建服務端與客戶端的TCP套接字。
創建TCP服務端
下面是一個在NodeJS中創建TCP服務端套接字的簡單例子,相關說明見代碼注釋。
var net = require('net');var HOST = '127.0.0.1';var PORT = 6969;// 創建一個TCP伺服器實例,調用listen函數開始監聽指定埠// 傳入net.createServer()的回調函數將作為」connection「事件的處理函數// 在每一個「connection」事件中,該回調函數接收到的socket對象是唯一的net.createServer(function(sock) {
// 我們獲得一個連接 - 該連接自動關聯一個socket對象
console.log('CONNECTED: ' +
sock.remoteAddress + ':' + sock.remotePort);
// 為這個socket實例添加一個"data"事件處理函數
sock.on('data', function(data) {
console.log('DATA ' + sock.remoteAddress + ': ' + data);
// 回發該數據,客戶端將收到來自服務端的數據
sock.write('You said "' + data + '"');
});
// 為這個socket實例添加一個"close"事件處理函數
sock.on('close', function(data) {
console.log('CLOSED: ' +
sock.remoteAddress + ' ' + sock.remotePort);
});}).listen(PORT, HOST);console.log('Server listening on ' + HOST +':'+ PORT);
服務端也可以用稍不同的方式接受TCP連接,即顯式處理"connection"事件:
var server = net.createServer();server.listen(PORT, HOST);console.log('Server listening on ' +
server.address().address + ':' + server.address().port);server.on('connection', function(sock) {
console.log('CONNECTED: ' +
sock.remoteAddress +':'+ sock.remotePort);
// 其它內容與前例相同});
上述兩個例子只是寫法不同,並無本質區別。
創建TCP客戶端
現在讓我們創建一個TCP客戶端連接到剛創建的伺服器上,該客戶端向伺服器發送一串消息,並在得到伺服器的反饋後關閉連接。下面的代碼描述了這一過程。
var net = require('net');var HOST = '127.0.0.1';var PORT = 6969;var client = new net.Socket();client.connect(PORT, HOST, function() {
console.log('CONNECTED TO: ' + HOST + ':' + PORT);
// 建立連接後立即向伺服器發送數據,伺服器將收到這些數據
client.write('I am Chuck Norris!');});// 為客戶端添加「data」事件處理函數// data是伺服器發回的數據client.on('data', function(data) {
console.log('DATA: ' + data);
// 完全關閉連接
client.destroy();});// 為客戶端添加「close」事件處理函數client.on('close', function() {
console.log('Connection closed');});
3. Nodejs發起http/TCP/UDP請求、串口通訊
通過node自帶的 http 模塊可以進行http請櫻悉做求,但陸基通常使脊衡用第三方庫 request 進行http請求
原生通過 net 模塊
原生通過 dgram 模塊
4. NodeJS編寫簡單TCP/UDP埠代理轉發服務
效果演示
5. TCP內網穿透的實現與原理(nodejs)
Nagent是TCP內網穿透實現,名稱來源於Nat與Agent的組合。類似frp項目,可以在區域網與互聯網提供橋梁。
前提是你要有一台流量伺服器並且有一個公網IP。如果沒有,也可以找服務商。
暫不能向frp那樣為HTTP服務,但可以實現簡單的分發————你只需要在兩台內網HTTP伺服器上運行Nagent客戶端即可。
項目位置:沒派 https://github.com/FettLuo/nagent
可以使用
未向特殊協議優化,例如http/s的轉發
雖然協議有涉及賬號名與密枯改賀碼,但未實現
未來希望你或我,向項目添加賬號管理支持,以webservice的形式支持
客戶端:運行在內網的Nagent客戶端。
服務端:運行在公網伺服器上的Nagent服務端。
用戶:互聯網上的實際用戶。
伺服器監聽在5670埠(默認)。
客戶端配置好自己的服務埠,也可以指定內網其他計算機。假設本機80埠。
客戶端登錄到伺服器,通知伺服器我需要監聽的外網埠,比如90。
一切正常的話(防火牆沒問題,埠沒被佔用等),伺服器上90埠的連接即會被導向到內網的80埠服務上。
客戶端與伺服器保持著一定數量的連接,每個連接都需要登錄成功。
用戶連接公網伺服器的埠後會從客戶端殲返的列表中彈出一個用於數據轉發。
當客戶端第一次收到數據時,建立與本地服務的連接,並發送/轉發數據。
需要NodeJS
windows/linux:
node nagent.js -s
linux:
./nagent.js -s
windows/linux:
node nagent.js -p 90 -P 80
linux:
./nagent.js -p 90 -P 80
保存下面內容到nagent.js所在的目錄,文件名為nagent.config,方括弧內替換為你的參數。
local_port=[你的本地服務埠]
server_port=5670// 服務端埠號
server_host='[服務端的主機地址,IP或域名均可]'
remote_port=[你需要服務端為你開放的公網埠]
keep_conn_count=10// 同時保持的最大連接數量