electron ant-design-vue 不能用_Electron与工业CCD通过TCP Server协议连接通讯

Electron与工业CCD通过TCP Server协议连接通讯

CCD可以理解为是一个相机,在工业上可以通过CCD给物体拍照,然后识别出物体表面激光刻印的信息,大概如下图,下图是我公司研发的软件一张截图,软件是使用C#实现的,这个工业软件还是很厉害的,里面涉及到了许多与工业传感器的数据交互。现在我的工作主要就是使用前端知识重构这个软件,要与硬件打交道了,当然要选择ElectronNode技术栈了。

f2c0bb5aeedbd06615b3bdf254e78ab5.png

CCD底层是通过TCP Server协议进行通讯的,所以要想与CCD进行数据对接,就要在Electron中实现TCP Server服务了。

这个知识我是不会的,最先是读C#的代码,看之前人家是怎么实现的,6000行的代码,看的我也是头晕脑胀的。再后来就是在网上找资料了,可是发现网上关于Electron连接TCP Server的资料真不多,但还是有的,下面就开始实现吧。

参考资料一:electron测试TCP通信,这篇文章写的估计也就只有博主自己能看懂吧!没办法参考着他的代码,我居然还悟出来点东西。

首先声明我的Electron是通过Vue CLI Plugin Electron Builder创建出来的。在主进程(background.js)中添加下面这段代码:

// TCP/IP通讯

// 试了半天,才发现这是创建一个 TCP Server 的
function createServer(port) {
  const HOST = '127.0.0.1';
  // const port = 7899;
  if (server) {
    server.close();
  }

  server = net.createServer();

  server.listen(port, HOST, function () {
    console.log('Server listen on port:' + server.address().address);
    console.log('--------------------------------------服务正在监听中---------------------------------------');
    sendServerData('start-server', '服务正在监听中,server is listening...');
  });


  server.on('connection', socket => {
    sendServerData('connect-server', 'Get conneciton from:' + socket.remoteAddress);

    socket.on('data', data => {
      sendServerData('data-server', 'Get data from socket:' + socket.remoteAddress + '. The data:' + data);
      socket.write('you said:' + data);
    });

    socket.on('close', () => {
      sendServerData('close-server', 'Socket:' + socket.remoteAddress + " closed");
    })
  });

}

let server;
let client;
let serverEvent, clientEvent;
// 通过这个方法就可以建立一个TCP服务器,当收到前端发送的event,就可以创建了,这里前端发送的消息是 start-server
ipcMain.on('start-server', (event, arg) => {
  serverEvent = event;
  // event.sender.send()
  console.log('+++++++++++++++++++++++++++ event ++++++++++++++++++++++++++++++++++++++++++++++')
  console.log(event)
  console.log('=================================== arg =============================================')
  console.log(arg)
  createServer(arg);
})

// 将消息返回给前端
function sendServerData(channel, msg) {
  try {
    console.log(`server send event ${channel}, ${msg}`);
    if (serverEvent) {
      serverEvent.sender.send(channel, msg);
    }
  } catch (error) {
    console.error('gt error:' + error);
  }
}

然后在前端页面上新增两个输入框和一个按钮,如下图:

994860012b70d9c0909e219936c622a5.png

Home.vue 代码:

<div class="home"><img alt="Vue logo" src="../assets/logo.png" /><div>
      发送的消息:<input type="text" v-model="msg" />div><div>
      接收的消息:<input type="text" v-model="msg2">div><div><button @click="tcpServer">TCP通信button>div>div>template><script>const ipc = window.require("electron").ipcRenderer;
ipc.on("start-server", (evnet, args) => {console.log(evnet,args)
});
ipc.on("data-server", (evnet, args) => {console.log(evnet,args)
});
ipc.on("close-server", (evnet, args) => {console.log(evnet,args)
});// @ is an alias to /srcimport HelloWorld from "@/components/HelloWorld.vue";export default {name: "Home",components: {
    HelloWorld,
  },
  data() {return {msg: "",msg2: "",
    };
  },methods: {
    tcpServer() {console.log(this.msg);
      ipc.send("start-server", this.msg);
    },
    addText(msg) {this.msg2 += msg + "\n";
    },
  },
};script><style lang="css" scoped>img {-webkit-app-region: drag;
}style>

下面这张图是主进程在控制台输出的信息,从中可以看出event参数是这么一大坨东西,arg参数就是我们输入框输入的111。

7cb6142066a78d9367ae493d425884ac.png

如果我们先通过网络调试助手,创建一个ip为 127.0.0.1 端口号为 7899 的 TCP Server,然后再回到页面上在输入框内也输入7899,然后点击按钮,就发现报错了,报错说127.0.0.1:7899已经被创建了。

f112f988f1dba2ed486e67a6395b0ef7.png

可以看出在主进程里面加的这段代码其实是通过渲染进程来创建一个TCP Server的,可这并不是我的需求,我的需求是将Electron作为一个客户端,可以向CCDTCP服务器发送消息,并且可以接收CCD返回给我的信息,下面实现一下。

参考资料二、electron 使用tcp套接字(一)

参考资料三、Node.js Net 模块

在主进程(background.js)中添加下面这段代码:

// 作为客户端
var net = require('net');
var HOST = '127.0.0.1';
var PORT = 7899;

var client = new net.Socket();
client.connect(PORT, HOST, function() {
    console.log('CONNECTED TO: ' + HOST + ':' + PORT);
    // 建立连接后立即向服务器发送数据,服务器将收到这些数据
    client.write('Hello TCP/IP! 老子终于通过 Electron 实现和你通信了!!!');

});

// 为客户端添加“data”事件处理函数
// data是服务器发回的数据
client.on('data', function(data) {
    console.log('DATA: ' + data);
    // 完全关闭连接
    client.destroy();
});

// 为客户端添加“close”事件处理函数
client.on('close', function() {
    console.log('Connection closed');
});

然后通过网络调试助手打开一个127.0.0.1:7899的TCP Server服务,我们通过Electron向网络调试助手发送一条消息。

374b48725fce3f2203de39e3584ad9ba.png

再次启动我们的Electron项目,项目一启动就会自动向网络调试助手发送一条信息,在网络调试助手中我们就可以看到这条消息了

65959f720640f2345a736ac96e8b5987.png

然后再通过网络调试助手给我们的客户端Electron发送一条数据:

6df79133634cb6df2fa0f863581f8213.png

然后我们的Electron也就可以收到来自TCP Server服务端的消息了,至此,大功告成。

8145f58e6af9baec28d285f129f5a957.png

最后贴出我主进程background.js的完整代码:

'use strict'

import {
  app,
  protocol,
  BrowserWindow,
  ipcMain,
} from 'electron'
import {
  createProtocol
} from 'vue-cli-plugin-electron-builder/lib'
import installExtension, {
  VUEJS_DEVTOOLS
} from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'

const net = require('net');
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win

// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([{
  scheme: 'app',
  privileges: {
    secure: true,
    standard: true
  }
}])

function createWindow() {
  // Create the browser window.
  win = new BrowserWindow({
    width: 800,
    height: 700,
    // 设置窗口的透明属性为true
    // transparent:true,
    // 禁用默认边框,无法拖拽移动窗口,也无法最大化、最小化、关闭窗口
    frame: false,
    // 透明的窗口不可调整大小,所以将resizable属性也设置为false
    // resizable:false,
    // 为了防止双击窗口可拖拽区域触发最大化事件,将maximizable属性也设置为false
    // maximizable:false,
    webPreferences: {
      // nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
      // 注意devTools可能会影响到transparent
      // devTools: false,
      nodeIntegration: true,
      // enableRemoteModule:true
    }
  })

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
    if (!process.env.IS_TEST) win.webContents.openDevTools()
  } else {
    createProtocol('app')
    // Load the index.html when not in development
    win.loadURL('app://./index.html')
  }

  win.on('closed', () => {
    win = null
  })
}

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow()
  }
})

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      await installExtension(VUEJS_DEVTOOLS)
    } catch (e) {
      console.error('Vue Devtools failed to install:', e.toString())
    }
  }

  // 最小化窗体
  ipcMain.on('minWindow', () => {
    win.minimize()
  })

  // 关闭窗体
  ipcMain.on('closeWindow', () => {
    win.close()
  })

  // 最大化窗体
  ipcMain.on('maxWindow', () => {
    win.isMaximized() ? win.unmaximize() : win.maximize()
  })

  createWindow()
})

// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
  if (process.platform === 'win32') {
    process.on('message', (data) => {
      if (data === 'graceful-exit') {
        app.quit()
      }
    })
  } else {
    process.on('SIGTERM', () => {
      app.quit()
    })
  }
}


// TCP/IP通讯

// 试了半天,才发现这是创建一个 TCP Server 的
// function createServer(port) {
//   const HOST = '127.0.0.1';
//   // const port = 7899;
//   if (server) {
//     server.close();
//   }

//   server = net.createServer();

//   server.listen(port, HOST, function () {
//     console.log('Server listen on port:' + server.address().address);
//     console.log('--------------------------------------服务正在监听中---------------------------------------');
//     sendServerData('start-server', '服务正在监听中,server is listening...');
//   });


//   server.on('connection', socket => {
//     sendServerData('connect-server', 'Get conneciton from:' + socket.remoteAddress);

//     socket.on('data', data => {
//       sendServerData('data-server', 'Get data from socket:' + socket.remoteAddress + '. The data:' + data);
//       socket.write('you said:' + data);
//     });

//     socket.on('close', () => {
//       sendServerData('close-server', 'Socket:' + socket.remoteAddress + " closed");
//     })
//   });

// }

// let server;
// let client;
// let serverEvent, clientEvent;
// // 通过这个方法就可以建立一个TCP服务器,当收到前端发送的event,就可以创建了,这里前端发送的消息是 start-server
// ipcMain.on('start-server', (event, arg) => {
//   serverEvent = event;
//   // event.sender.send()
//   console.log('+++++++++++++++++++++++++++ event ++++++++++++++++++++++++++++++++++++++++++++++')
//   console.log(event)
//   console.log('=================================== arg =============================================')
//   console.log(arg)
//   createServer(arg);
// })

// 将消息返回给前端
// function sendServerData(channel, msg) {
//   try {
//     console.log(`server send event ${channel}, ${msg}`);
//     if (serverEvent) {
//       serverEvent.sender.send(channel, msg);
//     }
//   } catch (error) {
//     console.error('gt error:' + error);
//   }
// }


// 作为客户端
var HOST = '127.0.0.1';
var PORT = 7899;

var client = new net.Socket();
client.connect(PORT, HOST, function() {
    console.log('CONNECTED TO: ' + HOST + ':' + PORT);
    // 建立连接后立即向服务器发送数据,服务器将收到这些数据
    client.write('Hello TCP/IP! 老子终于通过 Electron 实现和你通信了!!!');
});

// 为客户端添加“data”事件处理函数
// data是服务器发回的数据
client.on('data', function(data) {
    console.log('DATA: ' + data);
    // 完全关闭连接
    client.destroy();
});

// 为客户端添加“close”事件处理函数
client.on('close', function() {
    console.log('Connection closed');
});
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: electron 是一个开源的跨平台框架,可以用来开发桌面应用程序。它基于 Chromium 和 Node.js,使得使用 web 技术(HTML、CSS 和 JavaScript)开发桌面应用成为可能。 在 electron 中,C 是一种强大且高效的编程语言,常用于为 electron 应用程序编写底层系统级别的功能。C 可以通过 electron 的 addon 机制与 JavaScript 代码进行通信。 通过 electron 的 addon 机制,我们可以将 C 语言中的代码编译成动态链接库(.dll 或者 .so 文件),然后在 JavaScript 代码中调用这些动态链接库中的函数。这样,我们就可以借助 C 语言的能力来处理一些底层的系统任务,比如访问硬件设备、调用操作系统的 API 等。 为了实现 electron C 通信,我们首先需要在 C 语言代码中定义一些函数,这些函数完成特定的功能。然后,通过编写一些 C++ 代码,将这些 C 语言函数封装成 addon,以供 JavaScript 代码调用。最后,我们可以在 JavaScript 代码中通过 require 加载并调用这些 addon,实现与 C 语言的通信。 通过 electron C 通信,我们可以在 electron 应用程序中获得更高的性能和更多的功能。使用 C 语言编写一些底层的功能模块,可以提高程序的效率,并且能够更好地与操作系统进行交互,实现更复杂的功能。因此,electron C 通信为开发者提供了更大的灵活性和功能扩展的可能性。 ### 回答2: electron是一个用于构建跨平台桌面应用程序的开源框架,它结合了Node.js和Chromium,可以使用Web技术(HTML、CSS和JavaScript)来开发桌面应用程序。 在electron中,C语言可以用于编写插件或使用底层操作系统的特殊功能。在electron的主进程中,可以通过Node.js的child_process模块来创建子进程,从而调用C语言编写的可执行文件或动态链接库。通过子进程的标准输入输出,可以与C语言程序进行通信。 通常,在electron中实现与C语言的通信有以下几种方式: 1. 使用子进程通信:在electron的主进程中,可以通过child_process模块启动一个C语言编写的可执行文件,并通过标准输入输出与其进行通信。C语言程序可以通过stdin接收来自electron的数据,并通过stdout返回结果。 2. 使用插件通信:electron支持使用C或C++编写插件,这些插件可以通过V8引擎提供的接口与JavaScript进行通信。这种方式需要使用C或C++的桥接代码来实现JavaScript和C语言之间的数据转换。 3. 使用共享内存通信:electron主进程和C语言程序可以使用共享内存进行高效的数据传输。通过在两者之间创建共享内存区域,可以直接在内存中读写数据,避免了数据的拷贝和序列化操作。 以上是electron和C语言之间常用的通信方式,具体选择哪种方式取决于应用程序的需求和开发者的技术背景。无论选择哪种方式,都可以实现electron与C语言之间的有效通信,从而结合Web技术和底层功能,开发出功能丰富且高性能的桌面应用程序。 ### 回答3: Electron是一个流行的跨平台应用程序开发框架,它结合了Node.js和Chromium,并允许开发者用Web技术构建桌面应用程序。在Electron中,使用主进程和渲染进程进行通信是非常常见的。 Electron使用IPC(进程间通信)机制来实现主进程和渲染进程之间的通信。IPC提供了几种方法来传递消息和数据: 1. 通过主进程的webContents对象可以向渲染进程发送消息。我们可以使用send()方法发送消息,并使用ipcRenderer.on()方法在渲染进程中监听和处理消息。这种方法可以应用于从主进程向渲染进程发送同步或异步消息,并获取返回结果。 2. 使用Remote模块可以简化主进程与渲染进程之间的通信。通过Remote模块,我们可以在渲染进程中直接调用主进程的模块和方法,就好像它们在同一个进程中一样。这样可以大大简化通信的代码。 3. 使用全局变量或文件来传递数据。主进程和渲染进程可以通过读取和写入共享的全局变量或文件来传递数据。这种方法对于传递较大的数据或复杂的对象可能更合适。 需要注意的是,Electron中的主进程和渲染进程是分开的,它们有不同的运行环境和权限。主进程可以访问底层系统API和资源,而渲染进程则专注于展示用户界面。因此,在进行通信时,我们需要考虑安全性和效率,并选择适合的方法。 总结起来,Electron中的主进程和渲染进程通信可以通过IPC、Remote模块和全局变量/文件来实现。根据实际需求选择合适的方法,可以很方便地在Electron应用中实现功能丰富且可靠的通信机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值