SoFunction
Updated on 2025-04-07

Implement multi-person chat room based on swoole

This article shares the specific code of swoole creating multi-person and multi-room chat rooms for your reference. The specific content is as follows

Core swoole code

The basic cs(client-sercer) structure remains unchanged, here the hash and set of redis to store and group; thus achieving functions such as grouping, statistics, and timed push; finally, the onclose event is used to eliminate disconnected connections, and the whole code is as follows: (If you don’t do the front-end, you won’t show it)

The core swoole

<?php 
 
namespace app\common; 
require_once ''; 
require_once ''; 
/**
 * socket object-oriented compilation
 */ 
class Ws 
{ 
  CONST HOST='0.0.0.0'; 
  CONST PORT='9501'; 
  public $ws=null; 
  public $getmsg=null; 
  public $server=null; 
 
  public function __construct() 
  {   
    $this->ws=new \swoole_websocket_server(self::HOST,self::PORT); 
    $this->ws->set([ 
      //The number of tasks must be set to start      'worker_num' => 4, 
      'task_worker_num' => 2, 
      // 'heartbeat_check_interval' => 5, 
      // 'heartbeat_idle_time' => 10, 
    ]); 
    // Listen to the new port    $this->server=$this->ws->listen("127.0.0.1", 9502, SWOOLE_SOCK_TCP); 
    //Close the websocket mode    $this->server->set([ 
      'open_websocket_protocol' => false, 
    ]); 
 
    $this->ws->on("start", [$this, 'onStart']); 
    $this->ws->on('open',[$this,'onopen']); 
    $this->server->on("receive", [$this, 'onReceive']); 
    $this->ws->on('task',[$this,'onTask']); 
    $this->ws->on('finish',[$this,'onFinish']); 
    $this->ws->on('message',[$this,'onmessage']); 
    $this->ws->on('close',[$this,'onclose']); 
    $this->server->on("close", [$this, 'oncloses']); 
    $this->ws->start(); 
  } 
  // Listen to data reception events  public function onReceive($serv, $fd, $from_id, $data) 
  { 
    $shuju=json_decode($data,ture); 
    // print_r($shuju).PHP_EOL; 
    if (empty($shuju['data'])) { 
      $this->ws->push(Predis::getInstance()->get('fd'), $data); 
    }else{ 
      if (empty($shuju['msg'])) { 
        //Execute asynchronous tasks        $this->ws->task($shuju); 
      }else{ 
        $push_arr=Predis::getInstance()->hvals($shuju['data']); 
        // echo "Cluster is:".print_r($push_arr);        foreach ($push_arr as $v) { 
          $this->ws->push($v, $shuju['msg']); 
        } 
      } 
    } 
  } 
  /**
    * Set the process name to smoothly restart the process for subsequent
    * @param $server
    */ 
  public function onStart($server) { 
    swoole_set_process_name("live_master"); 
  }    
  /**
     Listen to the callback of the event
   */ 
  public function onopen($server, $request) 
  { 
    print_r("The fd at this time is:",$request->fd); 
    Predis::getInstance()->set('fd',$request->fd); 
  } 
   
  /**
     Listen to the callback of the received event
   */ 
  public function onmessage($server, $frame) 
  { 
    $server->push($frame->fd, "{$frame->data}"); 
  } 
  /**
     Listen to a callback for a shutdown event
   */ 
  public function onclose($ser, $fd) 
  { 
    print_r("Hello,mine{$fd}\n"); 
    //Exit and delete the excess grouping fd    $group=Predis::getInstance()->sMembers('group'); 
    foreach ($group as $v) { 
      $fangjian=Predis::getInstance()->hgetall($v); 
      foreach ($fangjian as $k => $vv) { 
        if ($fd == $vv) { 
          Predis::getInstance()->hdel($v,$k); 
        } 
      } 
    } 
  } 
  public function oncloses($ser, $fd) 
  { 
    print_r("This isclient{$fd}\n"); 
  } 
 
  /**
   * $serv service
   * $task_id Task ID, automatically generated within the swoole extension, is used to distinguish different tasks
   * $src_worker_id $task_id and $src_worker_id are combined to be globally unique. The task IDs delivered by different worker processes may have the same
   * $data is the content of the task
   */ 
   public function onTask($serv,$task_id,$src_worker_id,$data) 
  { 
    //Introduce tasks    $obj = new Task; 
    $method = $data['data']; 
    $arr = $data['arr']; 
    //Publish specific tasks    $flag = $obj->$method($arr, $serv); 
    return $flag; // Tell the worker  } 
  /**
   * $task_id is the task ID
   * $data is the result of task processing
   */ 
   public function onFinish($serv,$task_id,$data) 
  { 
    print_r($data).'/n'; 
  } 
 
} 
 
new Ws(); 

Distribute tasks

<?php 
/**
  * It represents the subsequent tasks asynchronous tasks in swoole.
  * Date: 18/3/27
  * Time: 1:20 am
  */ 
namespace app\common; 
// include ''; 
 
class Task { 
  //Asynchronously create room  public function chuangjian($data,$serv) 
  { 
    $time=$data['time']*1000; 
    swoole_timer_after($time, function() use($data){ 
      //Create a room (modify the auction product status)      self::post("https://code./index/index/in"); 
    }); 
  } 
 
  //Enter the room and cache the information  public function jingru($data,$serv) 
  { 
    $fd=Predis::getInstance()->get('fd'); 
    //Add to group    Predis::getInstance()->hset($data['name'],$data['uid'],$fd); 
    // Join the group collection    Predis::getInstance()->sadd('group',$data['name']); 
  } 
 
 
  public function post($url,$params=false,$ispost=0) 
  { 
    $httpInfo = array(); 
    $ch = curl_init(); 
    curl_setopt( $ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1 ); 
    curl_setopt( $ch, CURLOPT_USERAGENT , 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22' ); 
    curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT , 30 ); 
    curl_setopt( $ch, CURLOPT_TIMEOUT , 30); 
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER , true ); 
    if( $ispost ) 
    { 
      curl_setopt( $ch , CURLOPT_POST , true ); 
      curl_setopt( $ch , CURLOPT_POSTFIELDS , $params ); 
      curl_setopt( $ch , CURLOPT_URL , $url ); 
    } 
    else 
    { 
      if($params){ 
        curl_setopt( $ch , CURLOPT_URL , $url.'?'.$params ); 
      }else{ 
        curl_setopt( $ch , CURLOPT_URL , $url); 
      } 
    } 
    //implement    $response = curl_exec( $ch ); 
    if ($response === FALSE) { 
      //echo "cURL Error: " . curl_error($ch); 
      return false; 
    } 
 
    $httpCode = curl_getinfo( $ch , CURLINFO_HTTP_CODE ); 
    $httpInfo = array_merge( $httpInfo , curl_getinfo( $ch ) ); 
    //Close the url request    curl_close( $ch ); 
    return json_decode($response,1); 
  } 
 
} 

Client

<?php 
namespace app\common; 
 
class Client 
{ 
  public $msg=''; 
 
  public $data=[]; 
 
  public function lianjie(){ 
 
    $cli = new \swoole_client(SWOOLE_SOCK_TCP); 
    //Judge connection status (synchronous connection mode)    $res=$cli->connect('127.0.0.1', 9502); 
    if (empty($res)) { 
      return "Connection failed"; 
    } 
 
    if (!empty($this->data)) { 
      //Send a message to the server      $rel=$cli->send(json_encode($this->data)); 
    }else{ 
      //Send a message to the server      $rel=$cli->send($this->msg); 
    } 
    if (!empty($rel)) { 
      return $rel; 
    }else{ 
      return flash; 
    } 
  } 
} 

Controller

<?php 
namespace app\index\controller; 
 
use app\common\Client; 
use app\common\Predis; 
use app\common\Sql; 
use app\index\model\User; 
 
class Index 
{ 
  //Create a room (add auction countdown)  public function chuangjian() 
  { 
    $data['time']=input("time"); 
    $data['id']=input("id"); 
    $cli = new Client(); 
    $cli->data = [ 
      'data' => 'chuangjian', 
      'arr' => $data 
    ]; 
    return $cli->lianjie(); 
  } 
  //Click to add hash (enter the room)  public function jingru() 
  { 
    $data['name']=input("name"); 
    $data['uid']=input("uid"); 
    $cli = new Client(); 
    $cli->data = [ 
      'data' => 'jingru', 
      'arr' => $data 
    ]; 
    return $cli->lianjie(); 
  } 
  //Push this room (the price is successful and pushed)  public function pushfan() 
  { 
    $data['fan']=input("fan"); 
    $cli = new Client(); 
    $cli->data = [ 
      'data' => $data['fan'], 
      'msg' => "Congratulations to user 111, Xi is a father!!!" 
    ]; 
    return $cli->lianjie(); 
  } 
  //The time ends and the push is specified  public function zhiding() 
  { 
    $data['fan']=input("fan"); 
    $cli = new Client(); 
    $cli->data = [ 
      'data' => $data['fan'], 
      'msg' => "Congratulations to user 111, Xi is a father!!!" 
    ]; 
    return $cli->lianjie(); 
  } 
 
} 

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.