swoole 的练习 demo(4)- 初具聊天室功能

swoole 的练习 demo(4)- 初具聊天室功能

一直不能下决心好好学习,仔细研究一下,决定用尽量降低难度曲线的方法,从易到难,一步一步的学习,所以整了个demo项目。

git仓库和使用步骤

确保能看到swoole,在 php -m 命令中
php -m 
git clone https://github.com/lang123789/swoole_demo.git
然后设置了标签,本文对应 v4.0
cd swoole_demo
git checkout v4.0

有提示错误之类,但代码已经切换到 v4.0 了。

另外,前面3版其实有一些js错误,一并修复了。

## 安装类库,生成 autoload.php 文件
composer install
## 启动 websocket 服务
php src/WebSocket/run.php

需求

6、需要能正常聊天。就是别人说话,其他每个在聊天室的人都能看到这个人说的话。
7、如果某人上线,他自己看到 欢迎您,某某某,其他人看到,某某某 上线了。
8、如果某人下线。其他人看到,某某某 下线了。

测试网址

127.0.0.1/index.php?id=1
127.0.0.1/index.php?id=2

主要代码

客户端主要代码

客户端代码主要在 index.php 中

function activate_chat_js() {

 const me = 1; 
 const chatter = 0;

 // 这是每个人自己发消息。子程序1。
 function update_chatWindow(incoming_message, from) {
   if (from === 1) { 
     var msg_html = my_message_html(incoming_message);
   } else if (from === 0) { 
     var msg_html = chatter_message_html(incoming_message); 
   } 
   $(".chat-window").append(msg_html);
 } 

 // 这是自己发消息。子程序2。
 function my_message_html(incoming_message) {
   var newMessage = '<div class="me-wrapper">' + '<div class="me-message container">' + incoming_message + '</div>' + '<div class="me-avatar">' + '我自己' +
 '</div></div>'; 
   return newMessage; 
 }

 // click btn to send message 
 // 这也是每个人自己发消息。最开始点击。
 $("#btn-send-message").click(function () {
   var user_input_area = $("#user-input-value"); 
   if (user_input_area.text().length == 0) {

   } else { 
     var message=user_input_area.text();
     update_chatWindow(user_input_area.text(), 1);
     user_input_area.text("");
     $('.chat-window').scrollTop($('.chat-window')[0].scrollHeight);
     // v4.0修改,把消息给服务器。
     window.websocket.send("my_message|{$user_id}|"+ message);
   } 
 });

 // ctrl+enter send message 
 // 这也是每个人自己发消息,用回车键。
 $('#user-input-value').keydown(function (e) { 
   if ((event.keyCode == 10 || event.keyCode == 13)) { 
     $('#btn-send-message').trigger("click"); 
     event.cancelBubble = true; 
     event.preventDefault();
   } 
 }); 
}

// 这是显示在中间的系统消息。由服务器推送。
function system_chatWindow(incoming_message) {
   var msg_html = '<div class="system-message">' + incoming_message + '</div>' ;          
   $(".chat-window").append(msg_html);
   $('.chat-window').scrollTop($('.chat-window')[0].scrollHeight);
}

 // v4.0 ,这是被onmessage函数调用的方法,
// 这是其他人发的消息,广播到每个机器。
function update_chatWindow2(incoming_message, from) {
   var msg_html = '<div class="current-chatter-wrapper">' + '<div class="chatter-avatar">' + from + '</div>' + '<div class="chatter-message container">' + incoming_message + '</div>' + '</div>';     
   $(".chat-window").append(msg_html);
   $('.chat-window').scrollTop($('.chat-window')[0].scrollHeight);
}
window.onload = function(){  activate_chat_js();
  var wsServer = 'ws://{$JS_IP}:9501';
  var websocket = new WebSocket(wsServer); 
  window.websocket = websocket;    
  websocket.onopen = function (evt) { 
    console.log("Connected to WebSocket server.");
    websocket.send("my_id|{$user_id}");
  };
  websocket.onclose = function (evt) { 
     console.log("Disconnected");
   };
   websocket.onmessage = function (evt) { 
     console.log('Retrieved data from server: ' + evt.data);
     var user = JSON.parse(evt.data);
     if (user.type=='my_id'){
        system_chatWindow(user.message);
      } 
      // v4.0修改。其他人接受某人的消息广播。
      if (user.type=='my_message'){
          update_chatWindow2(user.message, user.from_user_name );
      }     
  };

   websocket.onerror = function (evt, e) { 
     console.log('Error occured: ' + evt.data);
   };
}

服务端主要代码

public function message(\swoole_websocket_server $server, \swoole_websocket_frame $frame)
{

    $data = $frame->data;
    echo "有消息:".$data."\n";
    //这里用户发来的信息已经分类型了。my_id开头,说明是系统自动从客户端发送的信息,用于识别身份。
    if (preg_match('#^my_id#', $data)) {
        $user_id = explode("|", $data)[1];
        $arr = $this->user_all;
        $user_name = isset($arr[$user_id]) ? $arr[$user_id] : '';
        if (!$user_name) {
            //如果用户不存在,则我直接关闭连接。
            echo "非法连接。用户id:" . $user_id;
            $server->close($frame->fd);
            return;
        }
        $user = [
           'fd' => $frame->fd,
           'user_name' => $user_name,
           'user_id' => strval($user_id),
        ];
        echo "有个人刚上线,数据:" . json_encode($user, JSON_UNESCAPED_UNICODE);
        echo "\n";
        // 放入内存表
        $this->table->set($frame->fd, $user);

        //给本人看 欢迎您。
        $server->push($frame->fd, json_encode([
           'type' => 'my_id',
           'message' => '欢迎您,' . $user_name,
        ]));
        // 通知其他人 某某 上线了。
        foreach ($this->table as $row) {
            if ($row['fd'] != $frame->fd) {
                $server->push($row['fd'], json_encode([
                   'type' => 'my_id',
                   'message' => $user_name . ' 上线了',
                ]));
            }
        } 
    } elseif (preg_match('#^my_message#', $data)) {
        $user_id = explode("|", $data)[1];
        $message = explode("|", $data)[2];

        $arr = $this->user_all;
        $user_name = isset($arr[$user_id]) ? $arr[$user_id] : '';
        if (!$user_name) {
            //如果用户不存在,则w我直接关闭连接。
            echo "非法连接。用户id:" . $user_id;
            $server->close($frame->fd);
            return;
        }
        echo "有人发消息,内容:" . $message;
        echo "\n";

        // 通知其他人 ,进行广播
        foreach ($this->table as $row) {
              if ($row['fd'] != $frame->fd) {
                  echo "推送消息:" . $message."给fd:" . $row['fd'] ;
                  $server->push($row['fd'], json_encode([
                     'type' => 'my_message',
                     'message' => $message,
                     'from_user_name' => $user_name,
                  ]));
              }
        } 
    }
}

/**
 * 客户端关闭的时候
  *
 * @param \swoole_websocket_server $server
 * @param int $fd
 */
 public function close(\swoole_websocket_server $server, int $fd)
 {
    $user = $this->table->get($fd);
    $user_name = $user['user_name'];

    echo "有人下线,数据:" . json_encode($user, JSON_UNESCAPED_UNICODE);

    $this->table->del($fd);
    // 通知其他人 某某 下线了。
    foreach ($this->table as $row) {
        $server->push($row['fd'], json_encode([
           'type' => 'my_id',
           'message' => $user_name . ' 下线了',
        ]));
     }
}

WebSocketServer.php 是核心文件。

代码说明

这一版的功能总算象个样子了!
swoole挺好用的。

效果示例

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!