Try developing an online chat application with workerman

Keywords: PHP Javascript JQuery Mobile

Chat is a common feature, and Workerman is an open source, high performance, asynchronous PHP socket instant messaging framework.

 

What is Workerman?

Workerman is an open source, high performance, asynchronous PHP socket instant messaging framework.Supports high concurrency and stability, and is widely used in mobile app, mobile communication, WeChat applets, mobile service, network games, PHP chat rooms, hardware communication, smart home, vehicle networking, the Internet of Things and other areas of development.Support TCP long connection, Web ocket, HTTP and other protocols, and support custom protocols.It has many high-performance components such as asynchronous Mysql, asynchronous Redis, asynchronous Http, MQTT Internet of Things client, asynchronous message queue and so on.

 

Here's how we build and configure Workerman

Step 1: Start by composing the extensions you need in workerman.

 

Step 2: Download all demo s from the official website and put them in the directory of our project. I'm using the laravel framework here

 

 

In the picture, I put the entire project in HTTP/Controller/Workerman.

 

Step 3: We need to change the references of the following three files to the following.Otherwise path error will be reported

start_businessworker,start_gateway,start_register

 

After modification, we can run the corresponding startup file directly in liunx

 

 

Double-click start_for_win.bat if you are running under window

After running successfully, you should see the following interface

 

 

At this point, we have completed the workerman-based communication environment.Next, we can develop according to our own project requirements.Here's the highlight.All of our chats are modified logically in Events.php in the directory.

 

Here's some code I wrote for you.How to implement a chat function

Event.php

<?php
/**
 * This file is part of workerman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link http://www.workerman.net/
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 */

/**
 * Used to detect issues such as dead loops or long blockages in business code
 * If you find that the business is stuck, you can open the following declare (exclude//comment) and execute PHP start.php reload
 * Then look at the workerman.log for a while to see if there are any process_timeout exceptions
 */
//declare(ticks=1);

/**
 * Chat Main Logic
 * Primarily handling onMessage onClose
 */
use \GatewayWorker\Lib\Gateway;

class Events
{
  /**
   * When the client is connected
   * @param $client_id This ID is automatically generated for gatewayworker
   */
  public static function onConnect($client_id)
  {
    Gateway::sendToClient($client_id, json_encode(array(
      'type'   => 'init',
      'client_id' => $client_id
    )));
  }


  /**
   * When there is a message
   * @param int $client_id
   * @param mixed $message
   */
  public static function onMessage($client_id, $message)
  {
    // debug
    echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id session:".json_encode($_SESSION)." onMessage:".$message."\n";

    //The client passes json data
    $message_data = json_decode($message, true);
    if(!$message_data)
    {
      return ;
    }

    //Perform different business according to type
    switch($message_data['type'])
    {
      //Client responds to server's heartbeat
      case 'pong':
        return;
      //Client login message format: {type:login, name:xx, room_id:1}, add to client, broadcast to all client XX to enter chat room
      case 'login':
        //Determine if there is a room number
        if(!isset($message_data['room_id']))
        {
          throw new \Exception("\$message_data['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']} \$message:$message");
        }

        //Put room number nickname in session
        $room_id = $message_data['room_id'];
        $client_name = htmlspecialchars($message_data['client_name']);
        $_SESSION['room_id'] = $room_id;
        $_SESSION['client_name'] = $client_name;


        //Get a list of all users in the room
        $clients_list = Gateway::getClientSessionsByGroup($room_id);
        foreach($clients_list as $tmp_client_id=>$item)
        {
          $clients_list[$tmp_client_id] = $item['client_name'];
        }
//        $clients_list[$client_id] = $client_name;

        //Broadcast to all clients in the current room, XX enters the chat room message {type:login, client_id:xx, name:xx}
        $new_message = array('type'=>$message_data['type'], 'client_id'=>$client_id, 'client_name'=>htmlspecialchars($client_name), 'time'=>date('Y-m-d H:i:s'),'to'=>$message_data['to'],'room_id'=>$message_data['room_id'],
          'from'=>$message_data['from'],'tag'=>$message_data['tag']);
        Gateway::sendToGroup($room_id, json_encode($new_message));
        Gateway::joinGroup($client_id, $room_id);

        //Send a list of users to the current user
        $new_message['client_list'] = $clients_list;
        Gateway::sendToCurrentClient(json_encode($new_message));
        return;

      //Client Speech message: {type:say, to_client_id:xx, content:xx}
      case 'say':
        //Illegal Request
        if(!isset($_SESSION['room_id']))
        {
          throw new \Exception("\$_SESSION['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']}");
        }
        $room_id = $_SESSION['room_id'];
        $client_name = $_SESSION['client_name'];

        //Private chat
//        if($message_data['to_client_id'] != 'all')
//        {
//          $new_message = array(
//            'type'=>'say',
//            'from_client_id'=>$client_id,
//            'from_client_name' =>$client_name,
//            'to_client_id'=>$message_data['to_client_id'],
//'content'=>'<b> Say to you: </b>'. nl2br (htmlspecialchars ($message_data['content')),
//            'time'=>date('Y-m-d H:i:s'),
//          );
//          Gateway::sendToClient($message_data['to_client_id'], json_encode($new_message));
//htmlspecialchars($message_data['to_client_name']).'Say: </b>'. nl2br (htmlspecialchars ($message_data['content']));
//          return Gateway::sendToCurrentClient(json_encode($new_message));
//        }

        $new_message = array(
          'type'=>'say',
          'from_client_id'=>$client_id,
          'from_client_name' =>$client_name,
          'to_client_id'=>'all',
          'content'=>nl2br(htmlspecialchars($message_data['content'])),
          'time'=>date('Y-m-d H:i:s'),

        );
        return Gateway::sendToGroup($room_id ,json_encode($new_message));
    }
  }
  /**
   * When client disconnects
   * @param integer $client_id Client id
   */
  public static function onClose($client_id)
  {
    // debug
    echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} client_id:$client_id onClose:''\n";

    //Remove from the list of clients in the room
    if(isset($_SESSION['room_id']))
    {
      $room_id = $_SESSION['room_id'];
      $new_message = array('type'=>'logout', 'from_client_id'=>$client_id, 'from_client_name'=>$_SESSION['client_name'], 'time'=>date('Y-m-d H:i:s'));
      Gateway::sendToGroup($room_id, json_encode($new_message));
    }
  }

}
Client Page
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>and{{$to->name}}Dialogue</title>
  <script type="text/javascript" src="{{asset('js')}}/swfobject.js"></script>
  <script type="text/javascript" src="{{asset('js')}}/web_socket.js"></script>
  <script type="text/javascript" src="{{asset('js')}}/jquery.min.js"></script>
  <link href="{{asset('css')}}/jquery-sinaEmotion-2.1.0.min.css" rel="external nofollow" rel="stylesheet">
  <link href="{{asset('css')}}/bootstrap.min.css" rel="external nofollow" rel="stylesheet">
  <link href="{{asset('css')}}/style.css" rel="external nofollow" rel="stylesheet">
  <script type="text/javascript" src="{{asset('js')}}/jquery-sinaEmotion-2.1.0.min.js"></script>

  {{--<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>--}}

</head>
<style>
  #sinaEmotion {
    z-index: 999;
    width: 373px;
    padding: 10px;
    display: none;
    font-size: 12px;
    background: #fff;
    overflow: hidden;
    position: absolute;
    border: 1px solid #e8e8e8;
    top: 100px;
    left: 542.5px;
  }
</style>
<body onload="connect();" style="margin: auto; text-align: center;">
<div style="margin: auto;">
  <div style="border: 1px solid red; height: 40px; width: 500px; margin: auto;">
    {{--Dialog Window Header--}}
    <div>
      <div style="width: 80px; height: 40px; border: 1px solid blue; float: left">
        <img src="{{$to->heading}}" width="80px" height="40px">
      </div>
      <div style="width: 150px; height: 40px; border: 1px solid blue; float: left">
        {{$to->name}}
      </div>
    </div>
    {{--//Dialog Window Content --}
    <div class="content" style="width: 500px; height: 400px; border: 1px solid green; margin-top: 40px; overflow-y: auto">
      {{--The other party's avatar and text--}}
      {{--<div style="min-height: 50px;margin-top: 10px;">--}}
        {{--<div style="width: 50px;height: 50px; border: 1px solid red; margin-left:10px; float: left">--}}
          {{--<img src="{{$to->heading}}" width="50px" height="50px">--}}
        {{--</div>--}}
        {{--<div style="border: 1px solid red; float: left; min-height: 50px" >dsadsadsadsadsa</div>--}}
      {{--</div>--}}
      {{--My avatar and text--}}
      {{--<div style= "min-height:50px;margin-top: 10px;">--}}
        {{--<div style="width: 50px;height: 50px; border: 1px solid red; margin-left:10px; float: right">--}}
          {{--<img src="{{$from->heading}}" width="50px" height="50px">--}}
        {{--</div>--}}
        {{--<div style="border: 1px solid red; float: right; min-height: 50px" >dsadsadsadsadsa</div>--}}
      {{--</div>--}}
    </div>
    {{--Dialog Send Window--}}
    <form onsubmit="return onSubmit(); return false;" id="ajaxfrom">
      <input type="hidden" name="to" value="{{$to->id}}">
      <input type="hidden" name="from" value="{{$from->id}}">
      <input type="hidden" name="room_id" value="{{$room}}">
      <input type="hidden" name="tag" value="{{$tag}}">
      <textarea id="textarea" name="content" class="Input_text" style="margin: 0px; width: 501px; height: 213px;"></textarea>
      <div class="say-btn">
        <input type="button" class="btn btn-default face pull-left" value="Expression" />
        <button type="submit" class="btn btn-default">Publish</button>
      </div>
    </form>
    Room number{{$room}}
  </div>
</div>

</body>
</html>
<script type="text/javascript">
  if (typeof console == "undefined") {  this.console = { log: function (msg) { } };}
  //If the browser does not support websockets, this flash is used to automatically simulate the websocket protocol, which is transparent to developers
  WEB_SOCKET_SWF_LOCATION = "/swf/WebSocketMain.swf";
  //Open websocket debug for flash

Posted by pdpullmn612 on Mon, 09 Dec 2019 15:02:51 -0800