TCP/IP 是一种基础的网络通信协议,它定义了计算机之间如何在网络上进行数据传输。MQTT 是一种基于 TCP/IP 协议的消息传输协议,它是为低带宽和不可靠网络环境设计的,主要用于物联网设备之间的通信。
如果厂家发过来的协议是基于 TCP/IP 的,那么你可以直接使用 TCP/IP 协议进行通信,不一定需要使用 MQTT。但是,如果你的应用场景需要低带宽和高可靠性,或者需要实现设备之间的消息发布和订阅功能,那么使用 MQTT 可能会更加合适。
总的来说,是否使用 MQTT 取决于你的具体需求和应用场景。如果厂家没有明确要求使用 MQTT,你可以根据自己的需求选择合适的通信方式。 Workerman 是一个高性能的 PHP socket 服务器框架,可以用来开发 TCP、UDP、UnixSocket、Websocket 等多种协议的应用。以下是一个使用 Workerman 开发的基于 TCP/IP 的简单 socket 服务器和客户端的例子。
首先,确保你已经安装了 Workerman。如果没有安装,可以通过 Composer 来安装:
bash composer require workerman/workerman 然后,创建一个名为 tcp_server.php 的文件,用于启动 TCP 服务器:
php <?php require_once DIR . '/vendor/autoload.php';
use Workerman\Worker;
// 创建一个 Worker 监听 2345 端口,使用 tcp 协议通讯 $tcp_worker = new Worker ("tcp://0.0.0.0:2345");
// 启动 4 个进程对外提供服务 $tcp_worker->count = 4;
// 当客户端发来数据时 $tcp_worker->onMessage = function ($connection, $data) { // 向客户端发送 hello $data $connection->send ('hello ' . $data); };
// 运行 worker Worker::runAll (); 然后,创建一个名为 tcp_client.php 的文件,用于启动 TCP 客户端:
php <?php require_once DIR . '/vendor/autoload.php';
use Workerman\Worker; use Workerman\Connection\AsyncTcpConnection;
// 不需要设置 Worker,直接使用 AsyncTcpConnection 发送数据。 $connection = new AsyncTcpConnection ('tcp://127.0.0.1:2345');
// 当连接建立成功时,发送数据 $connection->onConnect = function ($connection) { echo "Connected to server\n"; $connection->send ("Hello World\n"); };
// 当连接收到服务端发送的数据时,打印数据并关闭连接 $connection->onMessage = function ($connection, $data) { echo "Received data: $data\n"; $connection->close (); };
// 如果连接失败,显示错误信息 $connection->onError = function ($connection, $code, $msg) { echo "Error: $msg\n"; };
// 当连接关闭时,显示日志 $connection->onClose = function ($connection) { echo "Connection closed\n"; };
// 连接服务端 $connection->connect (); 运行服务器:
bash php tcp_server.php start 在另一个终端运行客户端:
bash php tcp_client.php 客户端将连接到服务器,发送 "Hello World" 字符串,然后服务器会响应 "hello Hello World" 字符串。客户端收到响应后,将打印出来并关闭连接。
请注意,这只是一个非常基础的例子,实际使用中你可能需要处理更多的逻辑,比如异常处理、连接管理、协议编码解码等。
刚好对接过两个厂家的 tcp 设备,用的 swoole 做的服务端
遇到几个比较明显的坑
- 1、设备量如果不多的话,还是别开启 coroutine, 不然复杂程度暴增;
- 2、对接厂家协议需要注意下二进制数据和二进制字符串的区别,这里有遇到一些坑,直接使用包长度检测解决黏包问题。
- 3、如果需要控制指定设备还需要管理所有连接的 fd 和设备 id 的映射,建议是使用共用内存的实现进行管理(比如 swoole 的 table),使用 redis 的话就很痛苦。
- 4、如果不幸使用 coroutine,需要使用连接池管理连接(mysql 和 redis),这时候还要注意内存泄露的问题。
推荐文章: