websockets chat
Upgrade to ollyxar
A forma recomendada de instalar WebSockets é através do Composer.
# Install Composer
curl -sS https://getcomposer.org/installer | php
Em seguida, execute o comando Composer para instalar a versão estável mais recente do WebSockets:
php composer.phar require ollyxar/websockets-chat
Após atualizar o compositor, adicione o provedor de serviços ao array providers
em config/app.php
Ollyxar WSChat WSChatServiceProvider::class,
Você pode personalizar as variáveis abaixo adicionando o arquivo de configuração: websockets-chat.php
na pasta de configuração:
parâmetro | descrição | exemplo |
---|---|---|
manipulador | Classe Handler (extensões de Worker) | AppMyHandler |
hospedar | Anfitrião (ip) | 0.0.0.0 |
porta | Porta | 2083 |
contagem_de_trabalhadores | Contagem de processos bifurcados | 4 |
use_ssl | Protocolo usado | false |
certificado | Certificado PEM | /etc/nginx/conf.d/wss.pem |
frase_senha | Senha do certificado PEM | secret$#% |
Este é um exemplo de como usar o Handler com autenticação de usuário. Se você tiver configuração padrão e armazenamento de sessão de arquivo, poderá usar este exemplo.
Primeiro você precisa instalar o auth-helper:
php composer.phar require ollyxar/laravel-auth
Em seguida, crie seu Handler.php
:
namespace App ;
use Generator ;
use Ollyxar LaravelAuth FileAuth ;
// or you can use RedisAuth if you're storing sessions in the Redis-server:
// use OllyxarLaravelAuthRedisAuth;
use Ollyxar WebSockets {
Frame ,
Handler as Worker ,
Dispatcher
};
/**
* Class Handler
* @package App
*/
class Handler extends Worker
{
/**
* Connected users
*
* @var array
*/
protected $ users = [];
/**
* Append connected user
*
* @param array $headers
* @param $socket
* @return bool
*/
private function fillUser ( array $ headers , $ socket ): bool
{
if ( $ userId = FileAuth:: getUserIdByHeaders ( $ headers )) {
// allow only one connection for worker per user
if (! in_array ( $ userId , $ this -> users )) {
$ this -> users [( int ) $ socket ] = $ userId ;
return true ;
}
}
return false ;
}
/**
* @param $client
* @return Generator
*/
protected function onConnect ( $ client ): Generator
{
$ userName = User:: where ( ' id ' , ( int ) $ this -> users [( int ) $ client ])-> first ()-> name ;
yield Dispatcher:: async ( $ this -> broadcast (Frame:: encode ( json_encode ([
' type ' => ' system ' ,
' message ' => $ userName . ' connected. '
]))));
}
/**
* @param array $headers
* @param $socket
* @return bool
*/
protected function validateClient ( array $ headers , $ socket ): bool
{
return $ this -> fillUser ( $ headers , $ socket );
}
/**
* @param $clientNumber
* @return Generator
*/
protected function onClose ( $ clientNumber ): Generator
{
$ user = User:: where ( ' id ' , ( int )@ $ this -> users [ $ clientNumber ])-> first ();
$ userName = data_get ( $ user , ' name ' , ' [GUEST] ' );
yield Dispatcher:: async ( $ this -> broadcast (Frame:: encode ( json_encode ([
' type ' => ' system ' ,
' message ' => $ userName . " disconnected. "
]))));
unset( $ this -> users [ $ clientNumber ]);
yield ;
}
/**
* @param string $message
* @param int $socketId
* @return Generator
*/
protected function onClientMessage ( string $ message , int $ socketId ): Generator
{
$ message = json_decode ( $ message );
$ userName = User:: where ( ' id ' , ( int ) $ this -> users [ $ socketId ])-> first ()-> name ;
$ userMessage = $ message -> message ;
$ response = Frame:: encode ( json_encode ([
' type ' => ' usermsg ' ,
' name ' => $ userName ,
' message ' => $ userMessage
]));
yield Dispatcher:: async ( $ this -> broadcast ( $ response ));
}
}
Em seguida, adicione marcação na frente:
< div class =" chat-wrapper " >
< div class =" message-box " id =" message-box " > </ div >
< div class =" panel " >
< input type =" text " name =" message " id =" message " placeholder =" Message " />
< button id =" send-btn " class =" button " > Send </ button >
</ div >
</ div >
E código JS:
var wsUri = "ws://laravel5.dev:2083" ,
ws = new WebSocket ( wsUri ) ;
ws . onopen = function ( ) {
var el = document . createElement ( 'div' ) ;
el . classList . add ( 'system-msg' ) ;
el . innerText = 'Connection established' ;
document . getElementById ( 'message-box' ) . appendChild ( el ) ;
} ;
document . getElementById ( 'message' ) . addEventListener ( 'keydown' , function ( e ) {
if ( e . keyCode === 13 ) {
document . getElementById ( 'send-btn' ) . click ( ) ;
}
} ) ;
document . getElementById ( 'send-btn' ) . addEventListener ( 'click' , function ( ) {
var mymessage = document . getElementById ( 'message' ) . value ;
if ( mymessage === '' ) {
alert ( "Enter Some message Please!" ) ;
return ;
}
var objDiv = document . getElementById ( "message-box" ) ;
objDiv . scrollTop = objDiv . scrollHeight ;
var msg = {
message : mymessage
} ;
ws . send ( JSON . stringify ( msg ) ) ;
} ) ;
ws . onmessage = function ( ev ) {
var msg = JSON . parse ( ev . data ) ,
type = msg . type ,
umsg = msg . message ,
uname = msg . name ;
var el = document . createElement ( 'div' ) ;
if ( type === 'usermsg' ) {
el . innerHTML = '<span class="user-name">' + uname + '</span> : <span class="user-message">' + umsg + '</span>' ;
document . getElementById ( 'message-box' ) . appendChild ( el ) ;
}
if ( type === 'system' ) {
el . classList . add ( 'system-msg' ) ;
el . innerText = umsg ;
document . getElementById ( 'message-box' ) . appendChild ( el ) ;
}
document . getElementById ( 'message' ) . value = '' ;
var objDiv = document . getElementById ( 'message-box' ) ;
objDiv . scrollTop = objDiv . scrollHeight ;
} ;
ws . onerror = function ( e ) {
var el = document . createElement ( 'div' ) ;
el . classList . add ( 'system-error' ) ;
el . innerText = 'Error Occurred - ' + e . data ;
document . getElementById ( 'message-box' ) . appendChild ( el ) ;
} ;
ws . onclose = function ( ) {
var el = document . createElement ( 'div' ) ;
el . classList . add ( 'system-msg' ) ;
el . innerText = 'Connection Closed' ;
document . getElementById ( 'message-box' ) . appendChild ( el ) ;
} ;
php artisan websockets-chat:run
php artisan websockets-chat:send " Hello from system! "