基础介绍
(1)Swoole是一个面向生产环境的 PHP 异步网络通信引擎,使 PHP 开发人员可以编写高性能的异步并发 TCP、UDP、Unix Socket、HTTP,WebSocket 服务。Swoole 可以广泛应用于互联网、移动通信、企业软件、云计算、网络游戏、物联网(IOT)、车联网、智能家居等领域。 使用 PHP + Swoole 作为网络通信框架,可以使企业 IT 研发团队的效率大大提升。—百度百科
 (2)WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。 —百度百科
(3)那这篇的主题就是如何使用Swoole+WebSocket实现一个简易的聊天室。
熟悉网络通信协议的同学肯定不会陌生。
功能需求及问题处理
 web端:
  (1)每次刷新都会生成一个唯一的ID(id值从1开始).
  (2)第一次进入网站时会要求用户设置昵称并会与ID进行绑定。
 问题点:
  (1)刷新页面后用户标识(ID)会重新生成,之前生成ID被弃用。
  (2)websocket生成了新的用户ID,但是跟现在的无法形成关联关系。
 server端:
 (1)当用户进入聊天室后,发送广播给所有人并加入聊天群组(使用redis存储)。
 (2)当用户退出直播间后,发送广播给所有人并清除该用户的记录。
 (3)用户每发送一次消息都要形成新的记录广播给所有人。
 (4)用户生成新的昵称后把昵称推送给他。
 web端问题处理方法:
 (1)浏览器刷新时提醒用户刷新即将重新获得新的身份。
 (2)用户连接成功后记录用户name,每次连接把这个name带上,清除之前该name的绑定关系,形成新的关系。
演示地址
代码实现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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87<?php
include "RedisManager.php";
$server = new Swoole\WebSocket\Server("0.0.0.0", 8877);
// 客户端连接
$server->on('open', function (Swoole\WebSocket\Server $server, $request) {
    //连接成功把当前在线的用户返回
    $user_list = RedisConnect::getRedis()->hGetAll('message:user');
    alone($server, $request->fd, [
        'type' => 'first',
        'data' => $user_list
    ]);
});
// 接收客户端发送的消息
$server->on('message', function (Swoole\WebSocket\Server $server, $frame) {
    $message_data = json_decode($frame->data, true);
    $type = $message_data['type'];
    $data = $message_data['user_name'];
    if (isset($message_data['send_message'])) {
        $user_message = $message_data['send_message'];
    }
    switch ($type) {
        case 'save_user':
            $new_name = '大厦单子' . $frame->fd . '号';
            // 修改用户昵称
            RedisConnect::getRedis()->hset('message:user', $frame->fd, $new_name);
            // 把生成的用户昵称返回给他
            alone($server, $frame->fd, [
                'type' => 'new_name',
                'name' => $new_name,
                'id' => $frame->fd
            ]);
            // 广播消息给其他用户
            groupSending($server, [
                'type' => 'open',
                'name' => $new_name,
                'id' => $frame->fd
            ]);
            break;
        case 'send_message':
            $msg = [
                'id' => $frame->fd,
                'user_name' => $data,
                'message' => $user_message,
                'type' => 'message'
            ];
            // 接受用户发送的消息
            RedisConnect::getRedis()->lpush('message:user:say', $msg);
            groupSending($server, $msg);
            break;
    }
});
// 退出聊天室
$server->on('close', function ($ser, $fd) {
    $user = RedisConnect::getRedis()->hget('message:user', $fd);
    RedisConnect::getRedis()->hdel('message:user', $fd);
    $msg = [
        'id' => $fd,
        'user_name' => $user,
        'message' => '退出聊天室',
        'type' => 'close'
    ];
    groupSending($ser, $msg, $fd);
});
// 开启服务
$server->start();
// 群发消息
function groupSending($server, $msg, $self = null)
{
    foreach ($server->connections as $conn) {
        if ($conn == $self) break; //不再推送给当前退出的用户
        $server->push($conn, json_encode($msg));
    }
}
// 单独发消息
function alone($server, $fd, $msg)
{
    $server->push($fd, json_encode($msg));
}
| 1 | <!DOCTYPE html> | 
总结
 这篇文章只是简单的介绍前后端如何实现通信,很多的细节问题没有进行处理。
 UI比较low,这里大家只看代码就好了…
 更多关于Swoole的功能还待探索…敬请期待…
 
          
         
          
        