page contents

swoole 第6次课-1再画瓢:机器人案例及多端口监听

机器人案例,多端口监听

继续第5次课的最后一个案例

1知识补充:多端口监听

11).多端口监听的实现

class\062\listen\tcpServer.php

<?php
//创建Server对象,监听 0.0.0.0:9505 端口
$server_m = new Swoole\Server('0.0.0.0', 9505);

//监听连接进入事件
$server_m->on('Connect', function ($server, $fd) {
echo "Client: Connect.\n";
});

//监听数据接收事件
$server_m->on('Receive', function ($server, $fd, $from_id, $data) {
$server->send($fd, "Server: " . $data);
});

//监听连接关闭事件
$server_m->on('Close', function ($server, $fd) {
echo "Client: Close.\n";
});

/**************************多端口监听 start ********************************/

//返回port对象
$port1 = $server_m->listen("127.0.0.1", 9501, SWOOLE_SOCK_TCP);
/*$port2 = $server->listen("127.0.0.1", 9502, SWOOLE_SOCK_UDP);
$port3 = $server->listen("127.0.0.1", 9503, SWOOLE_SOCK_TCP | SWOOLE_SSL);*/

//设置每个port的回调函数
$port1->on('connect', function ($serv, $fd){
echo "Client:Connect.\n";
});

$port1->on('receive', function ($serv, $fd, $from_id, $data) {
$serv->send($fd, 'Swoole: '.$data);
$serv->close($fd);
});

$port1->on('close', function ($serv, $fd) {
echo "Client: Close.\n";
});

/*$port2->on('packet', function ($serv, $data, $addr) {
var_dump($data, $addr);
});*/


/**************************多端口监听 end ********************************/


//启动服务器
$server_m->start();

运行方法

打开两个shell,都进入对应目录,一个运行tcpServer.php,一个netstat -nalp | grep 950

attachments-2020-12-eVbDo51H5fd1636a180c0.jpg


12)多端口客户端的连接: 主服务的连接及作为监听服务的连接

服务器端:上述服务端class\062\listen\tcpServer.php,改造如下

<?php
//创建Server对象,监听 0.0.0.0:9505 端口
$server_m = new Swoole\Server('0.0.0.0', 9505);

//监听连接进入事件
$server_m->on('Connect', function ($server, $fd) {
echo "Client-{$fd}: Connect to m-server.\n"; //连接到$server_m的信息
});

//监听数据接收事件
$server_m->on('Receive', function ($server, $fd, $from_id, $data) {
$server->send($fd, "m_Server: " . $data); //$server_m发送的信息
});

//监听连接关闭事件
$server_m->on('Close', function ($server, $fd) {
echo "Client-{$fd}: Close.\n";
});

/**************************多端口监听 start ********************************/

//返回port对象
$port1 = $server_m->listen("127.0.0.1", 9501, SWOOLE_SOCK_TCP);


//设置每个port的回调函数
$port1->on('connect', function ($serv, $fd){
echo "Client-{$fd}:Connect to p-server.\n"; //连接到port1 的server的信息
});

$port1->on('receive', function ($serv, $fd, $from_id, $data) {
$serv->send($fd, 'p-Swoole: '.$data); //port1 的server发送的信息
$serv->close($fd);
});

$port1->on('close', function ($serv, $fd) {
echo "Client-{$fd}: Close.\n";
});

/**************************多端口监听 end ********************************/

//启动服务器
$server_m->start();

客户端: class\062\listen\tcpClient.php

<?php
$client = new Swoole\Client(SWOOLE_SOCK_TCP);
if (!$client->connect('192.168.204.168', 9505, -1)) { //连接到$server_m $client->connect('127.0.0.1', 9505, -1)这个对内形式也行
//if (!$client->connect('192.168.204.168', 9501, -1)) { //连接到$port1 这个形式不成功,提示端口已被占用。因为这个端口已经对内作为监听端口,不能用对外形式,只能用对内的形式,如下
//if (!$client->connect('127.0.0.1', 9501, -1)) { //连接到$port1的server
exit("connect failed. Error: {$client->errCode}\n");
}
$client->send("hello world\n");
echo $client->recv();
$client->close();


运行如下:注意客户端运行时要切换注释

attachments-2020-12-nDe8uJeC5fd1759807af4.png

说明:连接主服务器,客户端连接形式对内对外都可,一般用对外形式$client->connect('192.168.204.168', 9505, -1)。

           连接监听端服务器,客户端只能用对内形式$client->connect('127.0.0.1', 9501, -1),不能用对外形式$client->connect('192.168.204.168', 9501, -1)。

13)关闭服务

服务器端:上述服务端class\062\listen\tcpServer.php,改造为class\062\listen\tcpServerClose.php如下

<?php
//创建Server对象,监听 0.0.0.0:9505 端口
$server_m = new Swoole\Server('0.0.0.0', 9505);

//监听连接进入事件
$server_m->on('Connect', function ($server, $fd) {
echo "Client-{$fd}: Connect to m-server.\n"; //连接到$server_m的信息
});

//监听数据接收事件
$server_m->on('Receive', function ($server, $fd, $from_id, $data) {
$server->send($fd, "m_Server: " . $data); //$server_m发送的信息
});

//监听连接关闭事件
$server_m->on('Close', function ($server, $fd) {
echo "Client-{$fd}: Close.\n";
});

/**************************多端口监听 start ********************************/

//返回port 对象
$port1 = $server_m->listen("127.0.0.1", 9501, SWOOLE_SOCK_TCP);


//设置每个port的回调函数
$port1->on('connect', function ($serv, $fd){
echo "Client-{$fd}:Connect to p-server.\n"; //连接到port1 的server的信息
});

$port1->on('receive', function ($serv, $fd, $from_id, $data) use($server_m) {
$server_m->shutdown(); //引入主服务并关闭
$serv->send($fd, 'p-Swoole: '.$data); //port1 的server发送的信息
$serv->close($fd);
});

$port1->on('close', function ($serv, $fd) {
echo "Client-{$fd}: Close.\n";
});

/**************************多端口监听 end ********************************/

//启动服务器
$server_m->start();

客户端不变,class\062\listen\tcpClient.php,以$client->connect('127.0.0.1',9501, -1)连接到$port1的server

运行

attachments-2020-12-Go4R3Qhx5fd186ac6aae1.jpg


综上总结:多端口监听知识点

                 $port=$server->listen($ip, $port, $protocol); //返回一个对内监听的服务,这个服务客户端只能用内部形式访问

$server->shutdown();

            

2.机器人案例

功能:机器识别人 =》把信息传递给服务端 =》 服务端接收到这个信息之后又会返回给机器

要求:实现这个通信过程

提示:机器人是一个服务 ,后端也是个服务;机器利用客户端向后端发送信息,后端会回复 -》也可以以客户端的方式回复

           利用tcpserver与client


21)初步实现服务器端的通信:借助动态创建的客户端

        实现思路

       attachments-2020-12-5tCbsnCP5fd1fdb68ca6b.png

目录结构图

attachments-2020-12-D4SC1RQO5fd1fe6b3d6d6.png

后台服务:class\062\jhymachine\admin\AdminServer.php

<?php
use \Swoole\Server;
class AdminServer{
private $port='9501';
private $host='0.0.0.0';
private $server;

public function __construct()
{
echo swoole_get_local_ip()['ens33'].":".$this->port."\n";
$this->server=new Server($this->host,$this->port);
$this->onEvent();
}
public function onEvent(){
$this->server->on("connect",[$this,'connect']);
$this->server->on("receive",[$this,'receive']);
$this->server->on("close",[$this,'close']);
}
public function connect($server, $fd){
echo "Client_{$fd}:Connect to AdminServer.\n";
}
public function receive($server, $fd, $from_id, $data){
echo "AdminServer服务,接收到机器服务转发自外界的数据\n";
var_dump($data);
$server->send($fd, 'data of AdminServer back : '.$data); //admin 的server发送的信息
//$server->close($fd);*/
}

public function close($server,$fd)
{
echo "Client_{$fd}:Connect of AdminServer is Close.\n";
}

public function start()
{
echo "AdminServer is start\n";
$this->server->start();
}

}

(new AdminServer())->start();

 机器服务的监听服务:class\062\jhymachine\machine\Listen.php   

<?php

use \Swoole\Server;

class Listen
{
private $port = '9556';
private $host = '127.0.0.1';
private $server;
private $listen;

public function __construct($server)
{
$this->server=$server;
echo "监听:".$this->host. ":" . $this->port . "\n";
//多端口监听
$this->listen=$server->listen($this->host,$this->port,SWOOLE_SOCK_TCP);
$this->onEvent();
}

public function onEvent()
{
$this->listen->on("connect", [$this, 'connect']);
$this->listen->on("receive", [$this, 'receive']);
$this->listen->on("close", [$this, 'close']);
}

public function connect($server, $fd)
{
echo "Client_{$fd}:Connect to ListenServer.\n";
}

public function receive($server, $fd, $from_id, $data)
{
echo '接收到机器的数据';
var_dump($data);
/*$server->send($fd, 'ListenServer: '.$data); //admin 的server发送的信息
$server->close($fd);*/
}

public function close($server, $fd)
{
echo "Client_{$fd}:Connect of ListenServer is Close.\n";
}

}

 

机器服务:注意初始化创建监听对象,接收到外界客户端消息时动态创建新客户端,转化给后台,然后接收到后台返回的信息,再在接收消息方法里返回给外界

class\062\jhymachine\machine\MachineServer.php

<?php
require 'Listen.php';
use \Swoole\Server;

class MachineServer
{
private $port = '9505';
private $host = '0.0.0.0';
private $server;

public function __construct()
{
echo swoole_get_local_ip()['ens33'] . ":" . $this->port . "\n";
$this->server = new Server($this->host, $this->port);
//多端口监听
(new Listen($this->server)) ;
$this->onEvent();
}

public function onEvent()
{
$this->server->on("connect", [$this, 'connect']);
$this->server->on("receive", [$this, 'receive']);
$this->server->on("close", [$this, 'close']);
}

public function connect($server, $fd)
{
echo "Client_{$fd}:Connect to MachineServer.\n";
}

public function receive($server, $fd, $from_id, $data)
{
echo "MachineServer服务,接收到外界客户端的数据\n";
var_dump($data);
//转发给后台服务器 AdminServer
$return=$this->sendToAdmin('192.168.204.168',9501,$data);
var_dump($return);
//回信息给客户端
$server->send($fd, 'MachineServer转为自 '.$return); //admin 的server发送的信息
//$server->close($fd);
}

public function sendToAdmin($ip,$port,$data)
{
$client = new \Swoole\Client(SWOOLE_SOCK_TCP);
if (!$client->connect($ip, $port, -1)) { //连接到AdminServer
exit("connect failed. Error: {$client->errCode}\n");
}
$client->send($data);
$return = $client->recv(); //AdminServer返回的信息
$client->close();
return $return;
}

public function close($server, $fd)
{
echo "Client_{$fd}:Connect of MachineServer is Close.\n";
}

public function start()
{
echo "MachineServer is start\n";
$this->server->start();
}

}

(new MachineServer())->start();

外界客户端 class\062\jhymachine\tcpClient.php

<?php
$client = new Swoole\Client(SWOOLE_SOCK_TCP);
//if (!$client->connect('192.168.204.168', 9501, -1)) { //连接到AdminServer
if (!$client->connect('192.168.204.168',9505, -1)) { //连接到MachineServer
exit("connect failed. Error: {$client->errCode}\n");
}
$client->send("hello world\n");
echo $client->recv();
$client->close();

运行方法,打开三个xshell,如下运行,对比结果

attachments-2020-12-dcHpZvUi5fd1f958510d8.png

至此,服务间的通信功能基本实现 

注意: listen后面会用到,这里只是提前贴了代码了


未完待续

  • 发表于 2020-12-10 07:47
  • 阅读 ( 591 )

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
吉洪叶
吉洪叶

21 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章