cjtaylor-adepteo / xmpp-php

XMPP 的 PHP 库。

安装: 100

依赖: 0

建议者: 0

安全性: 0

星标: 0

关注者: 0

分支: 22

类型:

v3.0.1 2024-01-08 15:26 UTC

README

Latest Stable Version Total Downloads Latest Unstable Version Build Status License

这是由于网上缺乏此类库(至少是我能找到的具有良好文档的库),因此为使 PHP 能够与 XMPP 通信而实现的低级套接字实现。

XMPP 核心文档可以在以下链接找到:这里

安装要求和示例

项目要求在 composer.json 中给出(Composer 网站

您可以通过运行以下命令在项目中使用此库:

composer require norgul/xmpp-php

您可以通过更改凭据以指向您的 XMPP 服务器,在项目根目录下运行 php Example.php 来在 Example.php 文件中查看使用示例。

库使用

初始化

为了开始使用此库,您首先需要实例化一个新的 Options 类。主机、用户名和密码是必填字段,而端口号,如果省略,则默认为 5222,这是 XMPP 的默认端口号。

用户名可以是裸 JIDJID/resource 形式。如果您使用裸 JID,则资源将被自动添加。您可以通过使用 $client->iq->setResource() 显式设置资源来覆盖此操作。在第二种情况下,用户名将被自动解析为 usernameresource 变量。在 JID/resource/xyz 格式的情况下,第二个斜杠之后的所有内容都将被忽略。如果同时存在 JID/resource 以及使用 $client->iq->setResource() 方法,则最后定义的将具有优先权。

$options = new Options();

$options
    ->setHost($host)            // required
    ->setPort($port)            // not required, defaults to 5222
    ->setUsername($username)    // required
    ->setPassword($password);   // required

Options 对象对于建立连接和随后的所有其他请求都是必需的,因此一旦设置,就不应更改。

设置之后,您可以实例化一个新的 XmppClient 对象,并将 Options 对象传入。

XMPP 客户端类说明

由于 XMPP 全部关于 3 个主要报文(IQ、消息和存在),因此我创建了依赖于套接字实现的独立类,以便您可以直接通过调用报文方法发送 XML。

这意味着现在从 XmppClient 类构造函数中提供了 3 个报文,可以在客户端的具体类上用作链式方法。

当前的逻辑是 $client->STANZA->METHOD()。例如

$client->iq->getRoster();
$client->message->send();
$client->presence->subscribe();

连接到服务器

XmppClient 类除了作为报文包装器外,还提供了一些公共方法。

$client->connect() 方法执行以下操作

  1. 连接到在 XmppClient 构造函数中初始化的套接字
  2. 打开一个 XML 流与 XMPP 服务器进行交换
  3. 根据提供的凭据尝试与服务器进行身份验证
  4. 开始与服务器进行初始通信,这是最基本的,以便您开始使用

当前版本支持 PLAINDIGEST-MD5 身份验证方法。

默认支持 TLS。如果服务器支持 TLS,则库将自动尝试使用 TLS 连接并使连接安全。

如果您想显式禁用此功能,可以在 Options 实例上使用 setUseTls(false) 函数,以便禁用 TLS 通信。请注意,此功能将在支持 TLS 但不是必需的环境中工作。如果 TLS 是必需的,则程序将独立于您设置的选项连接到 TLS。

发送原始数据

send() 消息在 XmppClient 类中被公开,其目的是向服务器发送原始 XML 数据。为了正确工作,您发送的 XML 必须是有效的 XML。

获取原始响应

可以使用 $client->getResponse() 获取服务器响应(或更准确地说,是服务器端的持续 XML 会话)。如果您想看到来自服务器的所有连续流,可以在无限循环中使用它,或者在像 Ratchet 这样的 WebSocket 解决方案中使用它。

如果您想在控制台中查看接收到的响应的输出,可以调用 $client->prettyPrint($response) 方法。

接收消息和其他响应

如果您不感兴趣于来自服务器的完整响应,您也可以使用 $client->message->receive()(已删除 $client->getMessages(),因为它只是此方法的简写)来匹配消息标签与正则表达式,并返回匹配消息的数组。如果您想在终端中查看响应,可以这样做

do {
    $response = $client->message->receive();
    if($response)
        echo print_r($response);
} while (true);

断开连接

断开连接方法向服务器发送关闭 XML 以结束当前打开的会话并关闭打开的套接字。

Stanza 方法分解

记得从 这里 -> $client->STANZA->METHOD()

消息

send() - 向某人发送消息。接受 3 个参数,其中最后一个参数是可选的。第一个参数是要发送的实际消息(正文),第二个参数是消息的接收者,第三个参数是要发送的消息类型。默认为 chat

可能的消息类型可以在 这个 RFC 文档 中找到

receive() - 在 本节 中介绍

IQ

getRoster() - 不接受任何参数,获取当前认证用户的联系人列表。

setGroup() - 将指定的用户放入您提供的组中。该方法接受两个参数:第一个参数是要附加到指定用户的组名,第二个参数是该用户的 JID。

Presence

setPriority() - 为给定资源设置优先级。第一个参数是一个整数 -128 <> 127。如果没有第二个参数,则将设置当前使用的资源的优先级。其他资源可以作为第二个参数提供,而优先级将设置为此特定资源。

subscribe() - 接受 JID 作为参数,并要求该用户提供存在状态。

acceptSubscription() - 接受来自该用户的存在状态。

declineSubscription() - 拒绝来自该用户的存在状态。

会话

会话目前仅用于区分多个连接时产生的日志。

XmppClient 类接受第二个可选参数 $sessionId,您可以将系统中的会话 ID 传递给它,或者它将自动分配。

您可以通过 Options 对象($options->setSessionManager(false))禁用会话,因为它们可能在框架或类似环境中使用时与已建立的会话发生冲突。不用说,如果禁用了它,将第二个参数传递给 XmppClient 不会建立新的会话。

更多选项(非必需)

Options 对象可以接受更多选项,这些选项可以是链式传递的,但不是必需的。这些在 Options 类中的代码中进行了说明和注释

$options
    ->setProtocol($protocol)  // defaults to TCP
    ->setResource($resource)  // defaults to 'norgul_machine_' string + timestamp
    ->setLogger($logger)      // logger instance (logging explained below)
    ->setAuthType($authType)  // Takes on classes which implement Authenticable

套接字选项

大多数套接字选项默认已设置,因此无需修改此类,但您可以在执行 socket_read() 时更改套接字保持活动状态的超时时间,您可以使用 $socket->setTimeout() 来做到这一点。

日志记录

在新建立的会话中,库会在 logs/ 文件夹中创建一个 XMPP.log 日志文件。

您可以通过使用 setLogger($logger) 在实例化 Options 时手动设置日志记录器。该方法接受任何实现 Loggable 接口的对象,因此您可以创建自己的实现。

有趣的事实:这曾经是一个 PSR-3 日志记录器接口,但我认为这对于开发阶段来说有点过度了。

其他

Example.php 中的 sendRawXML() 方法可以帮助调试。该方法允许您提供手写的 XML 并将其发送到服务器。另一方面,您也可以通过提供方法名而不是 XML 来触发方法。

Enter XML: <xml>foo</xml>           <-- will send XML
Enter XML: getRoster                <-- will run getRoster() method
Enter XML: requestPresence x@x.com  <-- will run with argument requestPresence(x@x.com)

一些有效的 XMPP XML 将会被拒绝(例如发送 <presence/>),因为 simplexml_load_string() 无法将其解析为有效的 XML。在您需要执行一些此类自定义操作且您确信它是有效的 XMPP XML 的情况下,您可以删除解析行,仅让 send() 方法发挥其魔力。

请注意!请非常小心! 向服务器发送无效的 XML 可能会破坏当前打开的 XML 会话,您可能需要重新启动脚本。这是高度实验性的,实际上并没有得到维护。这是一个被遗弃的糟糕方法,其父母遗弃了它并匆忙离开。它可能有一天会证明自己是哈利·波特,但嘿...我们都明显怀疑它。你可能是一个特别的雪花,但没有人喜欢你。继续前进到孤儿院!方法(只是开玩笑,我不会删除它)!

谁说自述文件是无聊的。

开发者文档

对于愿意贡献的人来说,结构的一个快速概述

  • Options.php - 关于库的所有可变内容
  • Socket.php - 与套接字相关的实现(连接、读取、写入等)
  • XmppClient.php - 与库交互的友好方法,并允许用户通过实例化类调用 stanza 方法。这应该包含尽可能少的逻辑,但实际上并不那么容易:)
  • AuthTypes - 包含用于在 XMPP 服务器上认证自己的方法。除了具体的实现外,还有一个抽象类,其中包含一些避免重复的少量逻辑,还有一个具有所有必要方法的接口,以便在需要新的认证类型时使用。

  • Buffers - 缓冲区(或者说是一个简单的数组)的实现,当套接字调用 receive() 方法时会填充,并在调用 getResponse() 方法(例如)等任何读取时刷新。简要的历史:我遇到了一个无法恢复的错误。在这种情况下,我必须做两件事:尝试重新连接,向用户显示错误。问题是 getResponse() 返回字符串,在重新连接的情况下,程序执行将继续返回空或返回错误字符串,在服务器第二次连接后,这会误导用户关于在重新连接之前发生的错误。缓冲区因此诞生。

  • Exceptions - 这基本上是一个标准。我只是覆盖了构造函数,以便我可以得到我的消息。

  • Loggers - 包含将日志存储到 logs/xmpp.log 文件中的逻辑。想法是在其中保留几种日志类型(完整、简单、无日志),但我发现一种就足够了。

Xml

  • Xml.php - 一个包含太多正则表达式匹配的 trait。这应该被重新格式化。
  • - 与服务器进行所有段通信的主要逻辑。这曾经只是普通的XML,但我决定在内部传递一个套接字依赖,这样当你调用该方法时,你实际上也会将其发送到服务器。这曾经像 $this->socket->send($this->iq->getRoster()) 这样,从编程角度来看是正确的,但出于简化起见,我更喜欢 $client->iq->getRoster()。我欢迎其他建议。

CI

持续集成是通过 Travis CI 实现的,每次推送都会经过一个当前非常简单的流程

  • 检查单元测试(天知道我有这么多)
  • 检查语法错误
  • 运行 phpcs(配置在 phpcs.xml 中)
  • 运行 phpmd(配置在 phpmd.xml 中)

待办事项

  • 单元测试 - 不幸的是,我已经拖延了太久,也许有喜欢编写测试的好心人。
  • 限流 - 当发生不可恢复的错误时(目前我正在捕获会打断流的 <stream:error> 错误),程序会自动重新连接。如果这种情况反复发生,程序将无限期地尝试连接,这在任何方面都是可以接受的,除了日志会被填满。我想限制连接,以便每次连接失败时增加连接时间。问题在于我只能捕获获取响应时的错误,而响应可能会在第一次XML交换时成功(例如,当你发送打开流请求时),而在第二次请求时失败。考虑到这一点,我的唯一想法是实现带有时间戳的限流。
  • 会话 - 我假设这部分工作正常,但应该从框架进行测试
  • 多个连接 - 我认为这部分工作得很好,但我担心在同时获取消息时触发 getRoster() 可能会删除一个服务器响应。如果你在一次批处理中同时获取名单和消息,它将被添加到缓冲区中。回调响应将获取名单或消息,而不是两者。然后缓冲区将被刷新。这是需要思考的问题。
  • XmppClient 结构 - 为了启用 $client->stanza->method,我需要在类中实例化所有段。我觉得这可以简化。