使用PHP和Websockets实时聊天应用程序

I want to create chat application in a webapp where user can chat with different site users. This will be available on web and also on iOS.

Instead of using traditional polling technique (send ajax hit to server in 1 sec interval), i want to use websockets.

Gone through couple of tutorials, but in all of them they have made PUBLIC GROUP chat. (Sample URL : https://www.sanwebe.com/2013/05/chat-using-websocket-php-socket)

Can anyone have idea to how to develop private chat using PHP & Websockets.

I have basic idea of websockets but how to use them to publish data on specific channel? And if we have 40 users so do we need to create 40 different channels?

Thanks in advance.

For private (room) chat systems you really have to develop your own logics. I would recommend you to use the following library:

http://socketo.me/

Go through their documentation at http://socketo.me/docs/ and start coding. If you get stuck then post your code and the community is here to help

There are not much different from doing one single global chat and multiple private channel. First, you need to design a protocol. Let create a simple protocol:

// client send to server
JOIN <channel_id>
LEAVE <channel_id>
MSG <channel_id> <message>

// server send to client
JOIN <channel_id> <username>
LEAVE <channel_id> <username>
MSG <channel_id> <username> <message>
  • So when a user connect to a server, you can randomly assign his username. You have an array to store all connection.
  • Create array of channel. Each channel hold an array of user inside the channel.
  • When client send JOIN <channel_id> to server. Broadcast JOIN <channel_id> <username> to all the connection in that channel.
  • When client send MSG <channel_id> <message> to server. Broadcast MSG <channel_id> <username> <message> to all connection in that channel.
  • so on and on ....

So basically, WebSocket provides a basic way of communicate, it is upto you to be creative to do thing.

This is how I have done in Laravel, You need to install Predis , socket.io , ratchet and other dependencies . Please check https://laracasts.com/discuss/channels/general-discussion/step-by-step-guide-to-installing-socketio-and-broadcasting-events-with-laravel-51

  1. Make one custom artisan command to run a websockets on some port using ratchet

    namespace App\Console\Commands;
    
    use Illuminate\Console\Command;
    
    use Ratchet\Server\IoServer;
    
    class webSockets extends Command
    {
        /**
         * The name and signature of the console command.
         *
         * @var string
         */
    
    protected $signature = 'run:socket {port?}';
    
    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Run websockets for specified port';
    
    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }
    
    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
            $port = $this->argument('port');
            $server = IoServer::factory(
            new ChatController(),$port
            $server->run();
    }
    

    }

Your controller should be like below

namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class ChatController implements MessageComponentInterface {
    public function onOpen(ConnectionInterface $conn) {
    }

    public function onMessage(ConnectionInterface $from, $msg) {
     //FIRE A BROADCAST EVENT HERE
      event(new MessageBroadcast(
                        $message, 
                        $datetime, 
                        $user_id
                        )
                );
    }

    public function onClose(ConnectionInterface $conn) {
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
    }
}

THE BROADCAST CLASS SHOULD LOOK LIKE BELOW

namespace App\Events;
use App\Events\Event;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;

class MessageBroadcast extends Event implements ShouldBroadcast
{
    use SerializesModels;

    public $message,$datetime,$userid;

    public function __construct($message,$datetime,$userid)
    {
        $this->message = $message;
        $this->datetime = $datetime;
        $this->userid = $userid;


    }

    public function broadcastOn()
    {
        return ['test-channel'.$this->user_id];
    }
}

Javascript part to subscribe a channel

<script src="{ { asset('js/socket.io.js') } }"></script>
    <script>
        //var socket = io('http://localhost:3000');
        var socket = io('http://yourip:5000');
        socket.on("test-channel1:App\\Events\\EventName", function(message){
            // get user on console 
             console.log(message);
        });
    </script>

You need to run following command in backgroud

1. php artisan run:socket <port_no>
2. Node yourjavascript.js