利用ThinkPHP6实现Websocket广播

来源:undefined 2024-12-26 18:59:17 1019

随着现代web应用程序的不断发展,实时通信成为了必须的功能之一。而websocket 技术就是其中一种最流行的实时通信方式,能够在服务器和客户端之间建立持久的双向连接,实现实时通信。

ThinkPHP 是一个非常流行的 PHP 框架,ThinkPHP 6 自带了 Swoole 扩展包,使得在使用 WebSocket 技术时变得非常简单。本文将介绍如何使用 ThinkPHP 6 框架来实现一个 WebSocket 广播功能。

环境要求

在开始之前,需要准备以下环境:

PHP 7.2+ Swoole 扩展 Composer 基本的 Web 开发知识

创建项目

首先,我们需要创建一个新的项目:

1

composer create-project topthink/think my-project

登录后复制

然后,为了方便使用 WebSocket,我们需要在项目的 composer.json 文件中添加 Swoole 扩展:

1

2

3

4

"require": {

"topthink/think-swoole": "^2.0",

"swoole/swoole": "^4.7"

}

登录后复制

完成后,运行以下命令进行安装:

1

composer install

登录后复制

创建控制器

接下来,我们需要创建一个控制器来处理 WebSocket 的请求。在 app/controller 目录下创建一个名为 Websocket.php 的文件,写入以下代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

<?php declare(strict_types=1);

namespace appcontroller;

use thinkswooleWebsocket as SwooleWebsocket;

use SwooleWebSocketFrame;

class Websocket extends SwooleWebsocket

{

/**

* 监听连接事件

* @param SwooleWebSocketServer $server

* @param SwooleHttpRequest $request

*/

public function onOpen($server, $request)

{

}

/**

* 监听接收消息事件

* @param SwooleWebSocketServer $server

* @param Frame $frame

*/

public function onMessage($server, Frame $frame)

{

}

/**

* 监听关闭事件

* @param SwooleWebSocketServer $server

* @param int $fd

*/

public function onClose($server, $fd)

{

}

}

登录后复制

在上面的代码中,我们继承了 thinkswooleWebsocket 类,并重写了其中的三个方法:

onOpen 方法用于监听连接事件; onMessage 方法用于监听接收消息事件; onClose 方法用于监听关闭事件。

当前,这些方法并没有做任何事情,接下来我们将会在这些方法中添加 WebSocket 通信的逻辑。

注册路由

在控制器创建好之后,我们需要在路由中进行注册。在 app/route.php 文件中添加以下内容:

1

2

3

use thinkacadeRoute;

Route::post(/ws, Websocket@onMessage)-&gt;middleware(    hinkmiddlewareAllowCrossDomain::class);

登录后复制

这里使用了 Route::post 方法来注册路由。这个路由的请求方式是 POST,路径为 /ws,并将请求映射到了 Websocket 控制器的 onMessage 方法上。

编写 WebSocket 通信逻辑

现在,我们已经完成了 WebSocket 路由和控制器的创建与注册。接下来,我们需要在控制器中添加 WebSocket 通信的逻辑。我们将使用 Swoole 的 WebSocket 服务端来实现 WebSocket 通信。

在 onOpen 方法中,我们可以获取客户端的连接对象,并将其存储起来,以便后续使用。在 onMessage 方法中,我们可以获取客户端发送的消息,并将这条消息广播给其它客户端。在 onClose 方法中,我们需要将客户端从连接池中移除。

在 app/controller 目录下创建一个名为 WebSocketServer.php 的文件,写入以下代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

<?php declare(strict_types=1);

namespace appcontroller;

use SwooleHttpResponse;

use SwooleWebSocketFrame;

use SwooleWebSocketServer;

use thinkswoolewebsocketHandlerInterface;

class WebSocketServer implements HandlerInterface

{

/**

* @var array $connections

*/

private $connections = [];

/**

* 监听连接事件

* @param Server $server

* @param SwooleHttpRequest $request

*/

public function onOpen(Server $server, SwooleHttpRequest $request): void

{

$this->connections[$request-&gt;fd] = $request-&gt;fd;

echo "client-{$request-&gt;fd} is connected

";

}

/**

* 监听消息事件

* @param Server $server

* @param Frame $frame

*/

public function onMessage(Server $server, Frame $frame): void

{

foreach ($this-&gt;connections as $fd) {

$info = $server-&gt;getClientInfo((int)$fd);

if ($info &amp;&amp; isset($info[websocket_status]) &amp;&amp; $info[websocket_status] == WEBSOCKET_STATUS_FRAME) {

$server-&gt;push($fd, $frame-&gt;data);

} else {

unset($this-&gt;connections[$fd]);

}

}

echo "received message from client-{$frame-&gt;fd}: {$frame-&gt;data}

";

}

/**

* 监听关闭事件

* @param Server $server

* @param int $fd

* @param int $reactorId

*/

public function onClose(Server $server, int $fd, int $reactorId): void

{

unset($this-&gt;connections[$fd]);

echo "client-{$fd} is closed

";

}

/**

* @param Response $response

*/

public function onHandShake(Request $request, Response $response): bool

{

// Do nothing

return true;

}

}

登录后复制

配置 WebSocket 服务

在写入 WebSocket 的服务代码之前,我们需要在 config 目录下创建一个名为 swoole.php 的配置文件,写入以下内容:

1

2

3

4

5

6

7

8

9

10

11

return [

socket_type =&gt; websocket,

host        =&gt; 0.0.0.0,

port        =&gt; 9501,

mode        =&gt; SWOOLE_PROCESS,

sock_type   =&gt; SWOOLE_SOCK_TCP,

settings =&gt; [

worker_num =&gt; swoole_cpu_num(),

],

handler =&gt; ppcontrollerWebSocketServer::class,

];

登录后复制

在上面的代码中,我们通过配置文件告诉应用程序如何启动 Swoole WebSocket 服务。我们启动 websocket socket 类型,绑定在 0.0.0.0:9501 上,并开启了多进程模式,使用 TCP 协议。worker_num 配置项设置了服务器的进程数,这里使用了 swoole_cpu_num() 用于返回系统 CPU 数量;handler 配置项指定了我们在上文中创建的 WebSocketServer 类。

运行 WebSocket 服务

在完成了创建、配置 WebSocket 服务的代码之后,我们需要运行一下代码,来开启 WebSocket 服务。在命令行中执行以下命令即可:

1

php think swoole start --mode=websocket

登录后复制

Websocket 服务已经启动,你可以通过访问你的应用程序来测试它。你可以使用这个地址:ws://your-domain:9501/ws。在浏览器中打开多个选项卡,分别测试 WebSocket 的连接、消息发送和接收等功能。

小结

本文介绍了如何使用 ThinkPHP 6 框架来实现一个 WebSocket 广播功能。我们通过创建控制器、注册路由和编写 WebSocket 通信逻辑,以及配置 WebSocket 服务,来完成这一功能。这个示例可以作为一个简单 WebSocket 最佳实践,为我们开发更高级的 WebSocket 功能提供了参考。

以上就是利用ThinkPHP6实现Websocket广播的详细内容,更多请关注php中文网其它相关文章!

最新文章