websockets chat
Upgrade to ollyxar
WebSocket을 설치하는 권장 방법은 Composer를 사용하는 것입니다.
# Install Composer
curl -sS https://getcomposer.org/installer | php
다음으로 Composer 명령을 실행하여 WebSocket의 최신 안정 버전을 설치합니다.
php composer.phar require ollyxar/websockets-chat
작곡가를 업데이트한 후 config/app.php
의 providers
배열에 서비스 공급자를 추가합니다.
Ollyxar WSChat WSChatServiceProvider::class,
config 폴더에 config-file: websockets-chat.php
추가하여 아래 변수를 사용자 정의할 수 있습니다.
매개변수 | 설명 | 예 |
---|---|---|
매니저 | 핸들러 클래스(작업자 확장) | AppMyHandler |
주인 | 호스트(IP) | 0.0.0.0 |
포트 | 포트 | 2083 |
작업자_수 | 분기된 프로세스 수 | 4 |
use_ssl | 사용된 프로토콜 | false |
인증서 | PEM 인증서 | /etc/nginx/conf.d/wss.pem |
비밀번호 문구 | PEM 인증서 암호 문구 | secret$#% |
이것은 사용자 인증으로 핸들러를 사용하는 방법의 예입니다. 기본 구성과 파일 세션 스토리지가 있는 경우 이 예제를 사용할 수 있습니다.
먼저 auth-helper를 설치해야 합니다:
php composer.phar require ollyxar/laravel-auth
그런 다음 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 ));
}
}
그런 다음 앞에 마크업을 추가합니다.
< 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 >
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! "