Electron + WebSocket + node.js 通信
描述
本文主要介紹了結合 Electron 和 node.js 進行 Websocket 通訊的一個簡單例子。
項目結構
- main.js:程序入口文件
- websocket.html:web視圖
- websocket.js :Websocket通訊腳本
技術
Node.js os 模塊
提供基本的系統操作函數。 ( 參考:Node.js 工具模塊 )
- 引入:
var os = require("os");
-
屬性
屬性 描述 os.EOL
操作系統的行尾符的常量 -
方法
方法 描述 os.tmpdir()
返回操作系統的默認臨時文件 os.endianness()
返回CPU的字節序,可能是“BE”或“LE” os.hostname()
返回操作系統的主機名 os.type()
返回操作系統名稱 os.platform()
返回編譯時的操作系統名 os.arch()
返回操作系統CPU架構,可能值:“x64”、“arm”、“ia32” os.release()
返回操作系統的發行版本 os.uptime()
返回操作系統運行的時間,單位:秒 os.loadavg()
返回一個包含 1、5、15 分鍾平均負載的數組。 os.totalmen()
返回系統內存總量,單位為字節。 os.freemem()
返回操作系統空閑內存量,單位是字節。 os.cpus()
返回一個對象數組,包含所安裝的每個 CPU/內核的信息:型號、速度(單位 MHz)、時間(一個包含 user、nice、sys、idle 和 irq 所使用 CPU/內核毫秒數的對象)。 os.networkInterfaces()
獲得網絡接口列表。
-
os.networkInterfaces()
返回的對象上的每個鍵都標識了一個網絡接口。 關聯的值是一個對象數組,每個對象描述了一個分配的網絡地址。
分配的網絡地址的對象上可用的屬性包括:
address
: IPv4或者IPv6地址。 netmask
: IPv4或者IPv6子網掩碼。 family
: IPv4
或IPv6
。mac
: 網絡接口的 MAC 地址。 internal
: 如果網絡接口是不可遠程訪問的環回接口或類似接口,則為 true
,否則為false
。scopeid
: 數值型的 IPv6 作用域 ID(僅當 family
為IPv6
時指定)。cidr
: 以 CIDR 表示法分配的帶有路由前綴的 IPv4 或 IPv6 地址。如果 netmask
無效,則此屬性會被設為null
。
測試:
//已分配網絡地址的網絡接口 var networkArr = os.networkInterfaces(); console.log(networkArr);
結果:
Websocket
-
Websocket是什么?
WebSocket 是 HTML5 開始提供的一種在單個 TCP 連接上進行全雙工通訊的協議 。
瀏覽器和服務器只需要完成一次握手,就可以創建持久性的連接,並進行雙向數據傳輸。
-
為何要選Websock?
很多網站為了實現推送技術,所用的技術都是 Ajax 輪詢。輪詢是指每隔一個特定時間,瀏覽器會向服務器發送一次HTTP請求,然后服務器返回數據給客戶端的瀏覽器。這種模式的缺點是瀏覽器需要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,這樣會浪費很多的帶寬等資源。
WebSocket 協議,能更好的節省服務器資源和帶寬,並且能夠更實時地進行通訊。
-
Websocket 創建
var Socket = new WebSocket(url, [protocol] );
url 必選,連接的 url。
protocol 可選,指定了可接受的子協議。
-
Websocket 屬性
屬性 描述 Socket.readyState
只讀屬性 readyState 表示連接狀態。0 - 連接未建立;1 - 連接已建立;2 - 連接正在進行關閉;3 - 連接已經關閉或者不能打開。 Socket.bufferedAmount
只讀屬性 bufferedAmount 已被 send() 放入正在隊列中等待傳輸,但是還沒有發出的 UTF-8 文本字節數。 -
Websocket 事件
事件 事件處理程序 描述 open Socket.onopen 連接建立時觸發 message Socket.onmessage 客戶端接收服務端數據時觸發 error Socket.onerror 通信發生錯誤時觸發 close Socket.onclose 連接關閉時觸發 -
Websocket 方法
方法 描述 Socket.send() 使用連接發送數據 Socket.close() 關閉連接
實現
websocket.js
在線 websoket 測試服務可以網上隨便找一個就行。
/**
* TCP/IP 通信
* 描述:跟所有相同網段的 ip 進行socket 連接
* 例如:當前ip:192.168.1.100,則與192.168.1.1 ~ 192.168.1.254的設備建立通信連接
*/
// 引入nodejs os模塊
var os = require("os");
//存儲 Websocket 對象數組
var websoketArray = [];
//在Electron中直接使用JQuery
if (typeof module === 'object') {window.jQuery = window.$ = module.exports;};
$(function(){
start();
});
/**
* 與相同網段建立通信連接
*/
function start(){
var ip = getIp();
if(ip != "localhost"){
ip = ip.substring(0,10);
//在線 websoket 測試服務:可直接使用
websoketArray.push(new createWebsocket("ws://123.207.136.134:9010/ajaxchattest"));
//與相同網段建立通信連接
for(var i = 1; i < 255; i++){
websoketArray.push(new createWebsocket("ws://" + ip + i));
}
}
}
/**
* 獲取本機IP
*/
function getIp(){
var ip = "";
try{
//已分配網絡地址的網絡接口
var networkArr = os.networkInterfaces();
for(var network in networkArr){
var ifaces = networkArr[network];
for (var i = 0; i < ifaces.length; i++) {
if(ifaces[i].family === "IPv4" && ifaces[i].address != "127.0.0.1" && !ifaces[i].internal){
//IPv4地址
ip = ifaces[i].address;
}
}
}
}catch(e){
//TODO handle the exception
ip = "localhost"
}
return ip;
}
/**
* 定義websocket 對象
*/
function createWebsocket(url){
var ws = new WebSocket(url);
//連接成功回調
ws.onopen = (evt) => {
console.log("Conenection open ...");
$("#chartRoom").append(
$("<p></p>").text("與 " + url + " 建立連接--成功")
);
}
//消息監聽
ws.onmessage = (evt) => {
console.log("msg");
document.getElementById('receivedMsg').innerHTML = event.data;
}
//連接失敗
ws.onerror = function(evt){
$("#chartRoom").append(
$("<p></p>").text("與 " + url + " 建立連接--失敗")
);
//關閉連接
ws.close();
//移除失敗的ws
websoketArray.splice(websoketArray.indexOf(ws),1);
console.log("移除 " + url + " 連接");
}
return ws;
}
/**
* 消息發送
* 給所有建立成功的連接發送消息
*/
function sendMsg(){
//消息內容
var msg = document.getElementById("sendMsg").value;
if(msg !== "" && msg !== undefined){
for(var i = 0; i < websoketArray.length; i++){
websoketArray[i].send(msg);
document.getElementById("sendMsg").value = null;
}
}
}
websocket.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebSocket demo</title>
<!-- bootstrap 4.5.0 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.0/dist/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<!-- Jquery 3.5 -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
</head>
<body>
<div class="container-fluid">
<h3>TCP/IP 協議通信</h3>
<div class="row mt-3">
<div class="col-8">
<textarea rows="6" id="sendMsg" style="width: 100%;"></textarea>
</div>
<div class="col-4">
<div class="btn-group-vertical">
<button type="button" class="btn btn-outline-info" onkeydown="sendMsg()" onclick="sendMsg()">發送</button>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div ></div>
<div class="jumbotron jumbotron-fluid">
<div class="container" id="chartRoom">
<h1 class="display-4">WebSocket 通信</h1>
<p class="lead">本機發送消息:<span id="receivedMsg"></span></p>
<a class="btn btn-primary btn-lg" href="javascript:;" onclick="start()" role="button">刷新連接</a>
<hr class="my-4">
</div>
</div>
</div>
</div>
</div>
<script src="../static/js/websocket.js"></script>
</body>
</html>