通常情况下,我们采用 TCP Socket 与智能硬件进行通信。外网环境中,有无数种解决方案:Swoole(PHP),Node.js,SuperSocket(.NET)…… 而在政企事业单位的内网环境,事情或许就不那么好办了。

0x01 目的

  • 接收来自硬件的数据,并在 Web 端展示。
  • 通过 Web 端操作,将指令下发至硬件。

0x02 限制

  • 浏览器需要支持 IE 等老版本浏览器。
  • 服务端需要支持 Windows Server 虚拟机(最低版本 2008)。
  • 纯内网环境,无法访问外网源,无法使用各类包管理器(其实可以自己搭建内网源,但过于复杂,人力成本太高)。

0x03 思路

目前公司 Web 后端语言均为 PHP,所以以下思路全部围绕 PHP 开展。

Plan A-1

既然围绕 PHP,首先我所想到的就是这种方案:

Ajax/Axios + PHP + Swoole + Hardware

前端之所以不采用 WebSocket,浏览器兼容性。

这也是我前几天的技术博客「Laravel + Swoole 实现 TCP/UDP Socket 服务端」所设想的,但很快这种方案被毙了,原因很简单:

  • Swoole 不支持 Windows。

Plan A-2

那么是否有办法在 Windows 下运行 Swoole?

  • Cygwin?毙了,内网不能下载包。
  • Hyper-V 虚拟机跑 Linux?毙了,嵌套虚拟化 Windows Server 2016 才支持。
  • VMware?Virtual Box?毙了,且不说物理机的虚拟层支持不支持嵌套虚拟化(Nested),就是支持,指不定卡成什么样。
  • Docker?不用想,毙了,Docker for Windows 基于 Hyper-V。

Plan B-1

毙了 Swoole,还有 Workerman 啊。

于是看了下 walkor/workerman-for-win,凉凉。

相比于 Workerman Linux 版本几千个 Star,简直尬啊。再加上 README 标明的:「此版本可用于 windows 下开发使用,不建议用在生产环境」。最后,看了看文档,Win 版本少了些对于提高性能十分有益的重要特性。

毙了。

Plan B-2

不死心,GitHub 上找找有没有小众又成熟的 PHP Socket 服务端。

前者内部未处理 TCP 粘包 问题,手动处理对于 PHP 组来说难度相当……巨大。

后者文档不全,非事件驱动,居然还是单进程、单线程的 while 循环。

毙了。

Plan C

于是决定,不得不换一门语言处理这个问题。「这门语言」必须具有:易部署、稳定、兼容 Windows 的特性。

尽管我首先想到的是微软的亲儿子 .NET,但另一门语言也浮现在我的脑海里:Node.js。

Node.js 本身所具有的事件驱动、非阻塞 IO 等特性十分适合用来开发 Socket 服务端;这一点在各类社区也得到印证,使用 Node 开发的 WebSocket、Socket 服务端层出不穷,且十分活跃;而微软的支持也不差,VS Code 就是基于 Node 开发。

但痛点也有,例如:全是回调,随着项目规模增长,回调越来越多,参数类型不明确,异常处理困难,万一哪里没写好造成隐藏 BUG,动不动就崩溃,麻烦可就大了。何况公司目前还没有专业玩 Node 的程序员。

个人认为,Node.js 自己玩玩入门简单,几行代码就能上手运行,但想要在生产环境下玩转 Node:一方面需要很强的编程思维功底,不然很难理解这种完全非阻塞的模式;另一方面需要对 Node 文档进行通读,具有一定了解、经验,否则万一某个变量类型搞错抛出异常,或是 Buffer 使用不当导致内存泄露,那都是隐性且致命的。

忍痛割爱!毙了。

Plan D

最后一个方案,.NET。大致思路是这样的。

Ajax/Axios + PHP + .NET + Hardware

  • .NET 方面采用成熟的 TCP/UDP 服务端组件 —— SuperSocket
  • PHP 与 .NET 相互通信,可以采用 Redis 消息队列,MySQL 中转等方案;也可以将 PHP 作为 TCP Client 对 SuperSocket 发送数据,当 SuperSocket 接收到硬件数据时,调用 PHP 编写的 HTTP API 即可。

这是目前我能想到的,结合现实情况,最节省人力物力成本,且相对稳定、简易的解决方案。部署时只需要:

  • 运行 WNMP,跑 PHP 代码。
  • 安装 .NET Framework,跑 .NET 服务端。

即可。

0x04 感想

内网,坑!