本文目錄一覽:
- 1、TCP內網穿透的實現與原理(nodejs)
- 2、nodejs中tcp服務器和http服務器實現的異同
- 3、nodejs可以接受tcp服務器的數據嗎
- 4、javascript socket tcp如何實現鏈接
TCP內網穿透的實現與原理(nodejs)
Nagent是TCP內網穿透實現,名稱來源於Nat與Agent的組合。類似frp項目,可以在局域網與互聯網提供橋樑。
前提是你要有一台流量服務器並且有一個公網IP。如果沒有,也可以找服務商。
暫不能向frp那樣為HTTP服務,但可以實現簡單的分發————你只需要在兩台內網HTTP服務器上運行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// 同時保持的最大連接數量
nodejs中tcp服務器和http服務器實現的異同
一,相同點
1,都調用了createServer方法。
2,當客戶端接入時都會執行一個回調函數。
二,不同之處
1,回調函數的中對象的類型。net服務器中,是個連接(connect)對象,而在HTTP服務器中,則是請求和響應對象。
2,原因:
1,http服務器是更高層的API,提供了控制和HTTP協議相關的一些功能。
2,瀏覽器在訪問站點時不會只用一個連接,很多主流的瀏覽器為了更快的加載網站內容,能夠像同一個主機打開八個不同的連接,並發送請求。Node為了不讓我們擔心是請求還是連接,為我們提供了請求和響應的抽象。因此,即使你能通過req.connection屬性獲得TCP連接對象,但大多數情況下你還是在與請求和響應的抽象打交道。
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())
})
javascript socket tcp如何實現鏈接
可以實現的
// 創建一個Socket實例
var socket = new WebSocket(‘ws://localhost:8080’);
// 打開Socket
socket.onopen = function(event) {
// 發送一個初始化消息
socket.send(‘I am the client and I\’m listening!’);
// 監聽消息
socket.onmessage = function(event) {
console.log(‘Client received a message’,event);
};
// 監聽Socket的關閉
socket.onclose = function(event) {
console.log(‘Client notified socket has closed’,event);
};
// 關閉Socket….
//socket.close()
};
參數為URL,ws表示WebSocket協議。onopen、onclose和onmessage方法把事件連接到Socket實例上。每個方法都提供了一個事件,以表示Socket的狀態。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/292684.html