【迅搜07】基础对象概览(二)服务器与命令对象及数据传输原理

这篇具有很好参考价值的文章主要介绍了【迅搜07】基础对象概览(二)服务器与命令对象及数据传输原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基础对象概览(二)服务器与命令对象及数据传输原理

在学习完最基础的 XS 对象和一些字段对象之后,我们今天将学习到的是 XS 的 PHP SDK 中非常核心的一个对象,那就是 XSServer 对象。从名字就可以看出,它是负责和服务端交互的,也就是 PHP 与 Xapian 的交互部分。要说搜索索引,最核心的应该是在索引和搜索的操作上,这两部分也是我们后面要重点关注的部分。但是,如果没有 XSServer 的支持,则一切都无法实现。幸好,这一部分的内容不多,也并不复杂,咱们就好好来看一下。

XSServer 服务器对象

XSServer 是 XSIndex 和 XSSearch 的父类,主要保存的是服务器的一些信息以及和服务器的交互。也就是说,和 Xapian 进行通信就是这个对象的主要工作。

咱们直接演示这个对象的一些属性打印出来的效果,先来看看它的构造函数,也就是实例化参数。

$server = new XSServer('localhost:8384', $xs);
echo $server->connString, PHP_EOL; // localhost:8384

XSServer 对象的构造参数有两个,第一个是连接地址和端口,第二个参数是一个 XS 对象。不过一般很少会去这样直接实例化,为啥呢?前面就说过了,XSIndex 和 XSSearch 都是继承自它的,所以这两个类的实例化对象也是有 XSServer 的方法的。而且单独的一个 XSServer 的作用有限,因此,在 XS 对象中也没有直接返回 XSServer 对象的属性方法,更多的还是使用它的两个子类。

$index = $xs->index;
echo $index->connString, PHP_EOL; // localhost:8383

$search = $xs->search;
echo $search->connString, PHP_EOL; // localhost:8384

注意看,索引对象和搜索对象返回的 connString 中的端口号是不同的。剩余的其它部分大家可以自己打印看一下,除了端口号不同之外,其它部分基本都是一样的。后续我们将使用 $search 对象进行余下的测试。

echo $search->project, PHP_EOL; // zyarticle
echo $search->socket, PHP_EOL; // Resource id #17
var_dump($search->xs === $xs); // bool(true)

这三个属性不用过多解释了吧。project 属性,对应 getProject()、setProject() 方法,用于获取和设置项目名,这个一会咱们再测试一下修改它之后会有什么效果;socket 对应 getSocket(),获取与服务器建立的连接的 Socket 句柄,没错,和后端服务器的连接是通过 TCP/Socket 进行连接通信的;xs 对应 getXs(),就是 XSServer 实例化时,传递进去的那个 XS 对象,也就是当前 XS 项目本身。

var_dump($search->hasRespond()); // bool(false)
if($search->hasRespond()){
 $search->respond; // 返回 XSCommand 对象
}

hasRespond() 方法用于判断当前连接是否有可读数据,一般如果需要调用 respond 或对应的 getRespond() 方法前,会先调用 hasRespond() ,用于避免 respond,getRespond() 在长连接读取数据时会阻塞等待。这一块大家了解一下就好,后面我们还会看到它的应用。。

修改 project

咱们来试试修改 project ,这个 project 就是配置文件以及 XS 项目对象中的 project.name 部分。XS 通过这个 project.name 来区分不同的索引项目,并且建立不同的索引项目目录。如果我们切换了,会产生什么效果呢?

$search->project = 'demo';
print_r($search->setLimit(1)->search(''));
//     Array
// (
//     [0] => XSDocument Object
//         (
//             [_data:XSDocument:private] => Array
//                 (
//                     [id] => 1
//                     [title] => 三号DEMO的,关于 xunsearch 的 DEMO 项目测试
//                     [category_name] => �\�r��
//                     [content] => 项目测试是一个很有意思的行为!
//                 )
// ………………………………

注意,默认我们实例化时,走的是 zyarticle 那个项目哦,切换成 demo 之后,查询的结果竟然直接就变成了 demo 项目里的数据了。

打开关闭连接

接着我们继续测试 close() 和 open() 这两个方法。上面的 project 不用改回来,一会咱们再解释原因。

$search->close();
try{
  print_r($search->search(''));
}catch(XSException $e){
  echo $e->getMessage(),PHP_EOL; // Broken server connection
}

close() 方法是用于关闭连接的,也就是关闭当前对象与服务器的那个 TCP/Socket 连接。当连接被关闭之后,查询也就无法进行了,直接会通过 XSException 异常对象返回 Broken server connection 的信息。

既然可以关闭连接,那么当然也可以再开启啦。

$search->open('8384');
// $search->reopen();
print_r($search->setLimit(1)->search(''));
//     Array
// (
//     [0] => XSDocument Object
//         (
//             [_data:XSDocument:private] => Array
//                 (
//                     [id] => 1
//                     [title] => 【PHP数据结构与算法1】在学数据结构和算法的时候我们究竟学的是啥?
//                     [category_name] => PHP
//                     [tags] => 数据结构,算法
//                     [pub_time] => 20220723
// ………………

open() 方法接收一个参数,就是端口号,用于搜索服务的端口号是 8384 ,所以咱们需要将 8384 传递进去。当然,这里也可以指定 IP Host 的,也就是 "localhost:8384" 这种形式也可以。另外,如果只是想重开之前的配置中的连接信息,那么直接使用 reopen() 方法就可以了,连参数都不用传。

接下来能够查询出内容,表明连接正常了。不过在这一小节的开头,我说过不用修改上一小节 project 的内容,也就是说,在进行 open() 之前,project 的值是 demo 呀,为啥查询之后的结果又变回 zyarticle 里面的内容了呢?

其实呀,原因很简单,就是 open() 方法在开启连接的时候,会按照 XS 项目对象来重置一些属性值。也就是说,project 被重置回 XS 对象中的 name 属性的内容了。

// 源码位置 /vendor/hightman/xunsearch/lib/XSServer.class.php
public function open($conn)
{
  $this->close();
  $this->_conn = $conn;
  $this->_flag = self::BROKEN;
  $this->_sendBuffer = '';
  $this->_project = null; // 看这里看这里
  $this->connect();
  $this->_flag ^= self::BROKEN;
  if ($this->xs instanceof XS) {  // 看这里看这里
    $this->setProject($this->xs->getName());
  }
}

设置超时时间

通过上面的属性信息,我们已经了解到了 XS 中,PHP SDK 与 Xapian 也就是 XS 的底层搜索引擎之间的交互是通过 Socket 来进行了。那么这样的长连接通常来说都是不限制超时时间的,也就是说,客户端主动断开连接,或者服务端出现问题,才会结束连接。不过,咱们也可以设置一个超时时间。

$search->setTimeout(1);
sleep(2);

try{
  print_r($search->search(''));
}catch(XSException $e){
  echo $e->getMessage(),PHP_EOL; // Failed to recv the data from server completely (SIZE:0/8, REASON:closed)
}

setTimeout() 用于设置连接超时时间,比如上面的测试代码咱们设置了一秒。然后 sleep() 两秒,再进行查询的时候,就会报出 Failed to recv the data from server completely 这样的错误。你可以再测试一下,将 setTimeout() 的时间加长一点,超过 sleep() 的时间,查询请求就都是正常的了。

执行与发送命令

最后,我们再来看一下命令的发送。这个命令的发送其实就是 PHP SDK 与 Xapian 的交互方法。不管是 XSIndex 还是 XSSearch ,在我们构造完索引或查询对象之后,最终都是通过 XSServer 中的 Socket 连接发送给服务端 Xapian 的。而接下来的这两个方法,就是最终发送时用到的方法。

  • sendCommand() 往服务器直接发送指令(无缓存)

  • execCommand() 执行服务端指令并获取返回值

上一小节的 setTimeout() 方法,本身就是通过向服务端发送超时配置信息来让服务端主动断开连接的,我们就拿它的代码来测试。(因为最简单)

// 源码位置 /vendor/hightman/xunsearch/lib/XSServer.class.php
public function setTimeout($sec)
{
  $cmd = array('cmd' => XS_CMD_TIMEOUT, 'arg' => $sec);
  $this->execCommand($cmd, XS_CMD_OK_TIMEOUT_SET);
}

代码就这两行,那么我们就拿到外面来测试一下。

$search->reopen(); // 上一小节如果超时关闭了,记得要重开一下

$cmd = array('cmd' => XS_CMD_TIMEOUT, 'arg' => 1);
$search->execCommand($cmd, XS_CMD_OK_TIMEOUT_SET);
sleep(2);
try{
  print_r($search->search(''));
}catch(XSException $e){
  echo $e->getMessage(),PHP_EOL; // Failed to recv the data from server completely (SIZE:0/8, REASON:closed)
}

可以看到效果是一样的。那么我们将 execCommand() 换成 sendCommand() 会怎么样呢?

大家可以自己试一下,异常信息会变成 Unexpected respond {CMD:128, ARG:208} 。这个原因就需要看一下这两个方法的源码了,这个不是我们学习的重点,简单来说的话,sendCommand() 只是发送数据,源码中非常简单,就是向 Socket 连接句柄中 write() 数据。而 execCommand() 不仅写,还读取了返回值,因此是一个完整的命令交互过程。所以说,Unexpected respond 的错误信息,就是写完之后在读缓冲区中有内容没有被取出来 ,到后面再次 search() 时,就会出现问题。既然这样,那就好解决啦。

$cmd = array('cmd' => XS_CMD_TIMEOUT, 'arg' => 1);
$search->sendCommand($cmd, XS_CMD_OK_TIMEOUT_SET); // Unexpected respond
sleep(2);
var_dump($search->hasRespond()); // bool(true)
if($search->hasRespond()){
  var_dump($search->respond);
  // object(XSCommand)#18 (5) {
  //     ["cmd"]=>
  //     int(128)
  //     ["arg1"]=>
  //     int(0)
  //     ["arg2"]=>
  //     int(208)
  //     ["buf"]=>
  //     string(0) ""
  //     ["buf1"]=>
  //     string(0) ""
  //   }
}
try{
  print_r($search->search(''));
}catch(XSException $e){
  echo $e->getMessage(),PHP_EOL; // Failed to recv the data from server completely (SIZE:0/8, REASON:closed)
}

前面的 hasRespond() 方法和 respond 属性没看到效果,这回就看到了吧,知道为什么 respond 会阻塞读了吧,因为咱们是 Socket 长连接读嘛,没有数据的时候它肯定就会阻塞着一直等待数据的到来。

XS_CMD_TIMEOUT 和 XS_CMD_OK_TIMEOUT_SET 都是 SDK 中自带的常量,也可以看成是与 Xapian 交互的命令代码(它们都是数字类型常量,可以点过去看看)。

这一段的内容只是抛砖引玉,我们这个系列不是分析源码的,但是,说实话,都已经写到这里了,具体的 PHP 部分的源码执行过程大家也可以继续顺着去研究了。说实话,整个 XS 的 PHP SDK 部分源码并不是非常的复杂。而 Xapian 和 SCWS 部分的源码就完全不用想了,之后如果能学学它们的单独使用就不错啦,毕竟全是 C/C++ 写的,只能留给各位大神来研究了。

后面我们要重点学习的 XSIndex 索引以及 XSSearch 搜索相关的内容,最终都是通过 XSServer 中的这两个方法进行数据传输的。

XSCommand 命令对象

通过上一节,细心的你一定会发现,XSServer 的 respond 属性会返回一个 XSCommand 对象。同时,如果你看了 execCommand() 或 sendCommand() 的源码,就会发现它们执行的第一件事也是在创建 XSCommand 对象。

// 源码 /vendor/hightman/xunsearch/lib/XSServer.class.php
public function execCommand($cmd, $res_arg = XS_CMD_NONE, $res_cmd = XS_CMD_OK)
{
  // create command object
  if (!$cmd instanceof XSCommand) {
    $cmd = new XSCommand($cmd);
 }
// …………………………
  $buf = $this->_sendBuffer . $cmd;
  $this->_sendBuffer = '';
  $this->write($buf);
// …………………………

在数据写入到 Socket 句柄时,也是将 XSCommand 拼接到写入的数据字符串中进入数据传递。也就是说,XSCommand 这个对象是一个命令对象,是与服务端进行交互的一个基本单位。

在这里可能有小伙伴会有疑问,_sendBuffer 貌似是一个字符串呀,_sendBuffer 和 XSCommand 对象拼接?这什么鬼?答案依然在源码中。

// 源码 /vendor/hightman/xunsearch/lib/XSServer.class.php XSCommand 类
public function __toString()
{
  if (strlen($this->buf1) > 0xff) {
    $this->buf1 = substr($this->buf1, 0, 0xff);
  }
  return pack('CCCCI', $this->cmd, $this->arg1, $this->arg2, strlen($this->buf1), strlen($this->buf)) . $this->buf . $this->buf1;
}

没错,XSCommand 对象重写了 __toString() 这个魔术方法。大佬真的是大佬,各种 PHP 特性功能的应用啊。很明显,这个 __toString() 最后 pack() 出来的二进制字符串,就是与 Xapian 进行交互的最终 API 了。就像是 ES 的 RESTFul API 一样。不过话说回来,ES 的交互真的太人性化了,直接用浏览器或者 CURL 工具就可以进行测试。而 Xapian 这种,想要通过命令行直接测试引擎里面的数据看来是不太可能了,真的必须就得通过 PHP 或者其它语言的 SDK 来操作了。或者各位大佬自己写一套?

这个对象其它部分就没什么内容了,几个属性都是和发送命令的参数相关的,只有两个方法:getArg() 和 setArg() ,也是用于获取和设置命令执行时的参数。

总结

好了,到此为止,XS 中的基本对象就介绍得差不多了。通过今天的内容,是不是感觉到服务端的交互其实也就这样。这就体现了基础知识的重要性,最后的交互 API 就是二进制数据使用 Socket 进行的嘛。好吧,说得简单,咱也没真实的写过纯 Socket 编程相关的项目。但是,多少还是看明白了这个过程。剩下的嘛,XSIndex 和 XSSearch 就是我们接下来要学习的核心内容了。另外,还有一个 XSDocument 对象,会在下一篇索引管理的第一篇文章中一起学习到。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/xunsearch/source/7.php

参考文档:

http://www.xunsearch.com/doc/php/api/XSServer

http://www.xunsearch.com/doc/php/api/XSCommand文章来源地址https://www.toymoban.com/news/detail-831005.html

到了这里,关于【迅搜07】基础对象概览(二)服务器与命令对象及数据传输原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • minio开源的对象存储服务器安装及使用

    MinIO是一个开源的对象存储服务器,设计用于实现高性能、可扩展的云存储。它兼容Amazon S3云存储服务的API,因此可以与现有的S3兼容应用程序进行集成。 MinIO可以部署在本地服务器、私有云环境或公共云上,如AWS、Azure、Google Cloud等。它通过将数据分散在多个独立节点上实现

    2024年02月08日
    浏览(51)
  • Automation服务器无法创建对象的原因及解决方法

    在编程中,当我们尝试在自动化服务器上创建对象时,有时会遇到\\\"Automation服务器不能创建对象\\\"的错误。这种错误通常发生在使用COM(Component Object Model)对象或通过自动化服务器来执行某些操作的情况下。本文将详细介绍这个问题的原因,并提供一些解决方法。 原因分析:

    2024年02月04日
    浏览(34)
  • Windows环境命令行CMD启动远程服务器上的bat文件,附查看远程服务器进程和按PID停止远程服务器进程命令

    Windows环境命令行CMD启动远程服务器上的bat文件,附查看远程服务器进程和按PID停止远程服务器进程命令 Windows环境命令行CMD启动远程服务器上的bat文件,命令如下: 执行后会返回启动的进程ID: 查看远程服务器进程命令: 按PID停止远程服务器进程命令:

    2024年02月07日
    浏览(71)
  • 从一个服务器复制东西到另一个服务器的命令

    您可以使用scp命令从一个服务器复制文件或目录到另一个服务器。以下是基本的scp命令格式: 其中,source是要复制的文件或目录的路径,destination是复制的目标路径,可以是本地路径或远程服务器路径。如果destination是远程服务器路径,则需要在路径前加上用户名和服务器地

    2024年02月14日
    浏览(48)
  • 服务器硬件规格常用查看命令——通用命令

    使用lshw命令可以查看服务器硬件配置的详细信息。使用它可以在支持DMI的x86或IA-64系统以及某些PowerPC机器上打印内存配置、固件版本、主板配置、CPU版本、G4可以工作)。目前该命令支持 CPU频率、缓存、总线速度等信息(已知PowerMac DMI(仅限x86和IA-64)、OpenFimware设备树(仅

    2024年02月05日
    浏览(56)
  • 服务器基本命令

    nohup python3 ./download-all-2023-11-01_12-08-11.py T85_download.log 标准输出重定向到文件 nohup bash test .sh stdout.txt 标准错误输出重定向到文件 nohup bash test .sh 2 stderr.txt 重定向到不同文件 nohup bash test .sh stdout.txt 2 stderr.txt 查看文件夹文件的个数 ls | wc -l 更改文件夹名称 剪切一定行数:546,

    2024年02月06日
    浏览(39)
  • Redis 服务器 命令

    可用版本: = 2.9.50 返回值: 返回 OK。如果 timeout 参数是非法的返回错误。 可用版本: = 1.0.0 返回值: 当 key 存在时,返回有关信息。 当 key 不存在时,返回一个错误。 可用版本: = 1.0.0 返回值: 总是返回 OK 。 可用版本: = 1.0.0 返回值: 保存成功时返回 OK 。 可用版本: = 2.2.12 返回值

    2024年01月16日
    浏览(52)
  • 服务器常用命令

    查看系统硬件设备信息 运行 查看服务器硬件设备信息,包括 BIOS信息(BIOS Information) 、 服务器信息(System Information) 、 CPU信息(Processor Information) 、 缓存信息(Cache Information) 、 内存信息(Physical Memory Array) 、 电源信息(System Power Supply) 、**内存设备(Memory Device)

    2024年02月19日
    浏览(41)
  • Unity 上传文件到阿里云 对象存储OSS服务器

    首先登录阿里云 免费试用–对象存储OSS --点击立即试用,可以有三个月的免费试用 创建Buket 新建AccessKey ,新建完成后,会有一个CSV文件,下载下来,里面有Key ,代码中需要用到 下载SDK 双击打开 sln文件,使用VS打开,右键项目–属性,修改程序集名字,然后点击生成–生成解

    2024年02月13日
    浏览(74)
  • Linux 命令|服务器相关

    【精选】在公共Linux服务器上创建自己的python虚拟环境_服务器创建自己的环境-CSDN博客 1. nvidia-smi命令详解-CSDN博客 2. 查看进程 top 和 ps 啥区别? ps 可以查看所有状态的进程? top 实时查看运行态的进程? 在本地 Mac 计算机的终端中,使用以下命令将文件上传到服务器 其中,

    2024年02月07日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包