我的electron教程系列

electron教程(一): electron的安装和项目的创建

electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google JavaScript Style Guide代码规范

electron教程(番外篇二): 使用TypeScript版本的electron, VSCode调试TypeScript, TS版本的ESLint

electron教程(二): http服务器, ws服务器, 子进程管理

electron教程(三): 使用ffi-napi引入C++的dll

electron教程(四): 使用electron-builder或electron-packager将项目打包为可执行桌面程序(.exe)

 

引言

 

这次, 我们一起通过几个例子, 进一步了解node.js+electron.

 

三个例子:

 

1.  搭建一个http服务器, 通过web对服务器进行访问

  2.  搭建一个ws服务器, 通过web向服务器发送消息

  3.  进程管理, 打开/关闭一个外部进程

 

例子1: 一个http服务器

 

1. 部署node.js+electron环境

按步骤完成electron教程(一): electron的安装和项目的创建所介绍的内容.

 

2. 安装http-server

确保你的cmd工作目录为项目根目录.

执行指令:

yarn add http-server --save

 

3. 在main.js中添加http服务器

在main.js的最下方, 添加如下代码:

// http-server
const httpServer = require('http-server'); httpServer.createServer().listen(8080);

在这段代码中:

我们创建了一个httpServer对象

const httpServer = require('http-server');

这个对象是通过http-server模块创建出来的.

使用httpServer对象, 创建一个http服务器, 并且监听了8080端口.

服务器启动后, 用户就可以通过浏览器来访问我们的服务器了.

 

4. 启动程序!

执行指令:

npm start

在自己的浏览器中,访问http://localhost:8080/index.html,就会得到本地的index.html文件



(这是chrome浏览器打开的效果)

 

例子2: 一个ws服务器

 

1. 部署node.js+electron环境

node.js+electron教程(一): 安装nodejs和electron

 

2. 安装ws

确保你的cmd工作目录为项目根目录.

执行指令:

yarn add ws --save

 

3. 在main.js中添加ws服务器

在main.js的最下方, 添加如下代码:

// ws-服务器
const WebSocketServer = require('ws').Server;
wss = new WebSocketServer({port: 12122});
wss.on('connection', (ws) => {
  // 有客户端连接时, 打印一条日志
  console.log('client connected');
  // 并且创建'message'监听
  ws.on('message', (message) => {
    // 直接将消息打印出来
    console.log(message);
  });
});

在这段代码中:

我们创建了一个WebSocketServer对象

const WebSocketServer = require('ws').Server;

这个对象是通过ws模块创建出来的.

使用WebSocketServer对象, 创建一个ws服务器叫做wss对象, 并且监听了12122端口.

为wss对象的两个事件分别绑定了回调:

connection事件, 有客户端连接时, 打印一条日志.

message事件, 直接将消息打印出来.

 

4. 在index.html中引入jquery

jquery官网下载jquery库, 将jquery.min.js放在html目录下的lib目录中.

并在index.html的<head></head>块中, 添加如下代码:

<script type="text/javascript" src="./lib/jquery.min.js"></script>

 

5. 在index.html中, 添加一个输入框和按钮

在index.html的<body></body>块中的最下方, 添加如下代码:

<div class="vertical-center">
    <div class="container">
        <p>&nbsp;</p>
        <form role="form" id="chat_form" onsubmit="sendWsMessage(); return false;">
            <div class="form-group">
                <input class="form-control" type="text" name="message" id="message"
                       placeholder="Type text to echo in here" value="" />
            </div>
            <button type="button" id="send" class="btn btn-primary"   
                    onclick="sendWsMessage();"> 
                Send!
            </button>
        </form>
    </div>
</div>

在这段代码中:

我们首先定义了一个输入框即表单form, 该表单包含了input元素, 用户可以在该输入框内填写字符, 而html可以通过message来获取输入框内的字符.

接着我们定义了一个按钮button, 在网页中按钮显示为send!, 并给该按钮的左键点击事件onclick绑定了一个函数onclick="sendWsMessage();", 当用户左键点击这个send!按钮, 就会触发sendWsMessage()函数.

 

6. 在index.html中, 定义ws客户端

在index.html的<script></script>块中的最下方, 添加如下代码:

const ws = new WebSocket("ws://localhost:12122");

这段代码中:

我们先实例化了一个websocket对象ws, 其参数为要连接的地址, 这里使用本机localhost的12122端口, 如果你是在局域网内启动, 也可以将localhost替换为你的内网ip.

 

7. 在index.html中, 定义按钮的sendWsMessage()函数

在index.html的<script></script>块中的最下方, 添加如下代码:

function sendWsMessage() {
  ws.send($('#message').val());
}

这段代码中:

我们调用了websocket对象wssend()方法, 向目标地址localhost的12122端口发送数据, 数据的内容是通过#message获取的, 即用户在输入框内输入的数据.

前端流程:

当用户点击send!按钮, 获取输入框内的内容, 通过ws, 向localhost的12122端口发送.

 

8. 启动

执行指令:

npm start

此时的程序界面, 出现了输入框send!按钮.

 

回到cmd中, 发现cmd打印了一条日志

client connected

那是因为我们在ws服务器(main.js)中, 添加了如下代码:

wss.on('connection', (ws) => {
  // 有客户端连接时, 打印一条日志
  console.log('client connected');

当程序启动的时候, 自动建立了连接, 所以打印了这条日志.

如果你已经完成了例子1, 并且还没有删除代码的话, 试着再次从浏览器中访问http://localhost:8080/index.html, 是否又打印出了一条相同的日志?

 

现在, 我们试试发送消息的功能:

在程序界面的输入框内, 输入一个Hello electron!, 点击send!

回到cmd中, 成功打印了日志Hello electron!.

 

前端流程:

当用户点击send!按钮, 获取输入框内的内容, 通过ws, 向localhost的12122端口发送.

后端流程:

当ws服务器收到消息的时候, 直接将消息打印出来.

 

例子3: 进程管理

 

1. 部署node.js+electron环境

node.js+electron教程(一): 安装nodejs和electron

 

2. 在main.js中, 启动一个外部进程

在main.js中, 添加如下代码:

const myChildProccess = require('child_process');

// 打开一个子进程notepad++
const mySpawn = myChildProccess.spawn(
    'e:\\Application\\Notepad++\\notepad++.exe');

在这段代码中:

我们创建了一个myChildProccess对象

  const myChildProccess = require('child_process');

这个对象是通过child_process模块创建出来的, 该模块主要用于创建子进程.

我们调用这个对象的spwan()方法, 启动一个子进程. 该方法接受一个字符串参数, 是子进程的路径, 注意路径的书写方式.

 

3. 测试

执行命令:

npm start

在程序启动后, notepad++也紧跟着启动了, notepad++就是本程序启动的子进程.

electron可以启动子进程, 自然也可以关闭子进程, 不然算什么进程管理?

 

现在我们关闭程序, 继续进行下一步.

 

4. 在index.html中, 添加一个按钮, 关闭子进程

在index.html的<body></body>块中的最下方, 添加如下代码:

<button onclick="killChildProcess()">关闭子进程</button>

在这段代码中, 我们添加了一个按钮button, 在网页中按钮显示为关闭子进程, 并给该按钮绑定了一个函数killChildProcess().

 

5. 创建renderer.js, 并添加到项目中

在html目录创建一个renderer.js文件

添加如下代码:

function killChildProcess() {
  // 发消息,由html的按钮调用,给主进程发消息,回调中关闭进程
  const ipcRenderer = require('electron').ipcRenderer;
  ipcRenderer.send('kill-child-now', 'get async message');
}

我们定义了关闭子进程按钮的点击函数killChildProcess(), 这个函数只有两行:

在函数的第一行, 创建了一个ipcRenderer对象

  const ipcRenderer = require('electron').ipcRenderer;

这个对象是通过ipcRenderer模块创建出来的, w3cschool是这样解释的:

ipcRenderer 模块是一个 EventEmitter 类的实例. 它提供了有限的方法,你可以从渲染进程向主进程发送同步或异步消息. 也可以收到主进程的响应.

简单的说, main.js是主进程, renderes.js是渲染进程, 在渲染进程调用ipcRenderer.send()方法, 可以发送消息. 在主进程可以收到消息, 如果你给这个消息绑定了回调, 收到消息后, 就会触发回调.

 

在函数的第二行, 我们发送了kill-child-now消息.

现在我们把renderer.js引入到项目之中

jquery相似, 在index.html的<head></head>块中, 添加如下代码:

<script type="text/javascript" src="../dist/renderer.js"></script>

 

6. 在main.js中, 监听消息, 绑定回调

在main.js的最下方, 添加如下代码:

// 监听消息, 关闭子进程
const ipcMain = require('electron').ipcMain; ipcMain.on('kill-child-now', (e, appUrl)=>{
  // 收到消息, 关闭进程
  mySpawn.kill();
});

在这段代码中:

我们创建了一个ipcMain对象

const ipcMain = require('electron').ipcMain;

这个对象是通过ipcMain模块创建出来的, w3cschool是这样解释的:

ipcMain 模块是类 EventEmitter 的实例.当在主进程中使用它的时候,它控制着由渲染进程(web page)发送过来的异步或同步消息.从渲染进程发送过来的消息将触发事件.

简单的说, ipcMain是使用在主进程中的, 负责监听从渲染进程中发送出来的消息.

( 还记得吗? 渲染进程是通过ipcRenderer发送消息的. )

我们用ipcMain对象监听了消息kill-child-now, 并且绑定了一个回调函数. 一旦收到这个消息, 就会触发这个回调函数.

回调函数只有一行, 简单直接:

mySpawn.kill( )

关闭在第三步中创建的子进程notepad++.

 

7. 启动

执行命令:

npm start

和之前的测试一样, 在程序启动后, notepad++也紧跟着启动了, notepad++就是本程序启动的子进程.

不一样的是, 程序界面上出现了一个按钮关闭子进程.

点击这个按钮试试看!

electron教程(二): http服务器, ws服务器, 进程管理的更多相关文章

  1. Cobalt Strike系列教程第四章:文件/进程管理与键盘记录

    Cobalt Strike系列教程分享如约而至,新关注的小伙伴可以先回顾一下前面的内容: Cobalt Strike系列教程第一章:简介与安装 Cobalt Strike系列教程第二章:Beacon详 ...

  2. electron教程(番外篇二): 使用TypeScript版本的electron, VSCode调试TypeScript, TS版本的ESLint

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google ...

  3. electron教程(一): electron的安装和项目的创建

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(二): http服务器, ws服务器, 进程管理 electron教程(三): 使 ...

  4. electron教程(三): 使用ffi-napi引入C++的dll

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(二): http服务器, ws服务器, 进程管理 electron教程(三): 使 ...

  5. electron教程(四): 使用electron-builder或electron-packager将项目打包为可执行桌面程序(.exe)

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(二): http服务器, ws服务器, 子进程管理 electron教程(三): ...

  6. electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google JavaScript Style Guide代码规范

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google ...

  7. 进程管理工具supervisor

    1. 简介 supervisor有两个组件:supervisord和supervisorctl,组成了client/server结构. supervisord负责读入配置文件,然后supervisor ...

  8. linux 使用进程管理工具 supervisor

    1.supervisor是使用python进行开发的运行在linux服务器上的进程管理工具 老版本的supervisor需要运行在python2环境,如果需要使用supervisor管理python3 ...

  9. 持续集成之二:搭建SVN服务器(subversion)

    安装环境 Red Hat Enterprise Linux Server release 7.3 (Maipo) jdk1.7.0_80 subversion-1.10.3.tar.gz apr-1. ...

随机推荐

  1. python 16 模块

    目录 模块 1. 自定义模块 1.1 模块分类 1.2 模块的导入 1.3 import 和 from 1.4 from 模块名 import * 1.5 模块的用法: 1.6 导入路径 2. tim ...

  2. MSIL实用指南-比较运算

    数值的比较就是大于.小于.等于.大于等于.小于等于.不等于,它们的运算结果都是布尔值.大于.小于.等于有直接对应的指令,分别是Cgt.Clt.Ceq.大于等于.小于等于.不等于没有直接对应的指令,它的 ...

  3. HTML 全局属性(摘自菜鸟教程)

    HTML 全局属性 New : HTML5 新属性. 属性 描述 accesskey 设置访问元素的键盘快捷键. class 规定元素的类名(classname) contenteditableNew ...

  4. java实现截取PDF指定页并进行图片格式转换

    1.引入依赖 <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox& ...

  5. 洛谷 P3627 【抢掠计划】

    题库:洛谷 题号:3627 题目:抢掠计划 link:https://www.luogu.org/problem/P3627 思路 : 这道题是一道Tarjan + 最长路的题.首先,我们用Tarja ...

  6. [python] - 读取文件内容,并输出

    1.读取文件,并逐行输出内容,代码如下: # coding=gbk import os path = 'E:\python_practice' os.chdir(path) fname = raw_i ...

  7. [python]python字典

    1.简介 字典是python中的映射数据类型,由‘键-值’(key-value)对构成. 键:几乎所有类型的python对象都可以用作键,不过一般还是以数字或者字符串最为常用. 值:可以是任意类型的p ...

  8. hdu 4513(Manacher)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4513 题解:就是在Manacher判断回文串的过程中添加一条条件 Ma[i + dp[i] - 2] ...

  9. JavaScript简单的弹幕

    弹幕 首先是弹幕的位置,是要从最右滑到最左,为了防止随机高度弹幕会覆盖的问题,设置了通道. 每一个通道是从左到右的一条,高度固定,这样不同通道的弹幕不会相互覆盖. 弹幕滑动就是简单设置CSS属性  t ...

  10. c语言实现字符指针(字符串)数组的排序

    需求: "ff555d", "114ddd", "114dd","aaa", "aaab", &qu ...