问题描述
我是网络套接字编程的新手。我正在 codeigniter 中实现网络套接字以实现简单的聊天功能,我的配置如下
$config['ratchet_client'] = array(
'host' => '127.0.0.1',// Default host
'port' => 8282,// Default port (be careful to set unused server port)
'auth' => true,// If authentication is mandatory
'debug' => true // Better to set as false in Production
);
现在当我在终端上启动服务器时它显示
Running server on host 127.0.0.1:8282
Authentication activated
New client connected as (81)
Client (81) authentication failure
Client (81) authentication success
Client (81) disconnected
一次所有四行,在我的控制台上,我收到以下消息
更新我的 Ratchet_client.PHP(在库文件夹中)是
<?PHP
defined('BASEPATH') or exit('No direct script access allowed');
// Namespaces
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;
use Ratchet\WebSocket\WsServer;
use Ratchet\ConnectionInterface;
use Ratchet\MessageComponentInterface;
/**
* @package CodeIgniter Ratchet WebSocket Library: Main class
* @category Libraries
* @author Romain galLIEN <romaingallien.rg@gmail.com>
* @license http://opensource.org/licenses/MIT > MIT License
* @link https://github.com/romainrg
*
* CodeIgniter library who allow you to make powerful applications with realtime interactions by using Websocket technology and RatchetPHP
*/
class Ratchet_client
{
/**
* CI Super Instance
* @var array
*/
private $CI;
/**
* Default host var
* @var string
*/
public $host = null;
/**
* Default host var
* @var string
*/
public $port = null;
/**
* Default auth var
* @var bool
*/
public $auth = false;
/**
* Default debug var
* @var bool
*/
public $debug = false;
/**
* Auth callback information
* @var array
*/
public $callback = array();
/**
* Config vars
* @var array
*/
protected $config = array();
/**
* Define allowed callbacks
* @var array
*/
protected $callback_type = array('auth','event');
/**
* Class Constructor
* @method __construct
* @param array $config Configuration
* @return void
* @author Romain galLIEN <romaingallien.rg@gmail.com>
*/
public function __construct(array $config = array())
{
// Load the CI instance
$this->CI = &get_instance();
// Load the class helper
$this->CI->load->helper('ratchet_client');
// Define the config vars
$this->config = (!empty($config)) ? $config : array();
// Config file verification
if (empty($this->config)) {
output('fatal','The configuration file does not exist');
}
// Assign HOST value to class var
$this->host = (!empty($this->config['ratchet_client']['host'])) ? $this->config['ratchet_client']['host'] : '';
// Assign PORT value to class var
$this->port = (!empty($this->config['ratchet_client']['port'])) ? $this->config['ratchet_client']['port'] : '';
// Assign AUTH value to class var
//$this->auth = (!empty($this->config['ratchet_client']['auth'] && $this->config['ratchet_client']['auth'])) ? true : false;
// Assign DEBUG value to class var
$this->debug = (!empty($this->config['ratchet_client']['debug'] && $this->config['ratchet_client']['debug'])) ? true : false;
}
/**
* Launch the server
* @method run
* @return string
* @author Romain galLIEN <romaingallien.rg@gmail.com>
*/
public function run()
{
// Initiliaze all the necessary class
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Server()
)
),$this->port,$this->host
);
// Run the socket connection !
$server->run();
}
/**
* Define a callback to use auth or event callback
* @method set_callback
* @param array $callback
* @return void
* @author Romain galLIEN <romaingallien.rg@gmail.com>
*/
public function set_callback($type = null,array $callback = array())
{
// Check if we have an authorized callback given
if (!empty($type) && in_array($type,$this->callback_type)) {
// Verify if the method does really exists
if (is_callable($callback)) {
// Register callback as class var
$this->callback[$type] = $callback;
} else {
output('fatal','Method ' . $callback[1] . ' is not defined');
}
}
}
}
/**
* @package CodeIgniter Ratchet WebSocket Library: Server class
* @category Libraries
* @author Romain galLIEN <romaingallien.rg@gmail.com>
* @license http://opensource.org/licenses/MIT > MIT License
* @link https://github.com/romainrg
*
* CodeIgniter library who allow you to make powerfull applications with realtime interactions by using Websocket technology and RatchetPHP
*/
class Server implements MessageComponentInterface
{
/**
* List of connected clients
* @var array
*/
protected $clients;
/**
* List of subscribers (associative array)
* @var array
*/
protected $subscribers = array();
/**
* Class constructor
* @method __construct
* @author Romain galLIEN <romaingallien.rg@gmail.com>
*/
public function __construct()
{
// Load the CI instance
$this->CI = &get_instance();
// Initialize object as SplObjectStorage (see PHP doc)
$this->clients = new SplObjectStorage;
// // Check if auth is required
if ($this->CI->ratchet_client->auth && empty($this->CI->ratchet_client->callback['auth'])) {
output('fatal','Authentication callback is required,you must set it before run server,aborting..');
}
// Output
if ($this->CI->ratchet_client->debug) {
output('success','Running server on host ' . $this->CI->ratchet_client->host . ':' . $this->CI->ratchet_client->port);
}
// Output
if (!empty($this->CI->ratchet_client->callback['auth']) && $this->CI->ratchet_client->debug) {
output('success','Authentication activated');
}
}
/**
* Event trigerred on new client event connection
* @method onopen
* @param ConnectionInterface $connection
* @return string
* @author Romain galLIEN <romaingallien.rg@gmail.com>
*/
public function onopen(ConnectionInterface $connection)
{
// Add client to global clients object
$this->clients->attach($connection);
// Output
if ($this->CI->ratchet_client->debug) {
output('info','New client connected as (' . $connection->resourceId . ')');
}
}
/**
* Event trigerred on new message sent from client
* @method onMessage
* @param ConnectionInterface $client
* @param string $message
* @return string
* @author Romain galLIEN <romaingallien.rg@gmail.com>
*/
public function onMessage(ConnectionInterface $client,$message)
{
// broadcast var
$broadcast = false;
// Check if received var is json format
if (valid_json($message)) {
// If true,we have to decode it
$datas = json_decode($message);
}
// Once we decoded it,we check look for global broadcast
$broadcast = (!empty($datas->broadcast) and $datas->broadcast == true) ? true : false;
// Count real clients numbers (-1 for server)
$clients = count($this->clients) - 1;
// Here we have to reassign the client ressource ID,this will allow us to send message to specified client.
if (!empty($datas->user_id) && $datas->user_id !== $client->resourceId) {
// At this moment we have to check if we have authent callback defined
if (!empty($this->CI->ratchet_client->callback['auth']) && empty($client->subscriber_id)) {
// Call user personnal callback
$auth = call_user_func_array($this->CI->ratchet_client->callback['auth'],array($datas));
// Verify authentication
if (empty($auth) or !is_integer($auth)) {
output('error','Client (' . $client->resourceId . ') authentication failure');
// Closing client connexion with error code "CLOSE_ABnorMAL"
$client->close(1006);
}
// Add UID to associative array of subscribers
$client->subscriber_id = $auth;
// Output
if ($this->CI->ratchet_client->debug) {
output('success','Client (' . $client->resourceId . ') authentication success');
}
}
}
// Now this is the management of messages destinations,at this moment,4 possibilities :
// 1 - Message is not an array OR message has no destination (broadcast to everybody except us)
// 2 - Message is an array and have destination (broadcast to single user)
// 3 - Message is an array and don't have specified destination (broadcast to everybody except us)
// 4 - Message is an array and we want to broadcast to ourselves too (broadcast to everybody)
if (!empty($message)) {
// We look around all clients
foreach ($this->clients as $user) {
// broadcast to single user
if (!empty($datas->recipient_id)) {
if ($user->subscriber_id == $datas->recipient_id) {
$this->send_message($user,$message,$client);
break;
}
} else {
// broadcast to everybody
if ($broadcast) {
$this->send_message($user,$client);
} else {
// broadcast to everybody except us
if ($client !== $user) {
$this->send_message($user,$client);
}
}
}
}
}
}
/**
* Event triggered when connection is closed (or user disconnected)
* @method onClose
* @param ConnectionInterface $connection
* @return string
* @author Romain galLIEN <romaingallien.rg@gmail.com>
*/
public function onClose(ConnectionInterface $connection)
{
// Output
if ($this->CI->ratchet_client->debug) {
output('info','Client (' . $connection->resourceId . ') disconnected');
}
// Detach client from SplObjectStorage
$this->clients->detach($connection);
}
/**
* Event trigerred when error occured
* @method onError
* @param ConnectionInterface $connection
* @param Exception $e
* @return string
* @author Romain galLIEN <romaingallien.rg@gmail.com>
*/
public function onError(ConnectionInterface $connection,\Exception $e)
{
// Output
if ($this->CI->ratchet_client->debug) {
output('fatal','An error has occurred: ' . $e->getMessage());
}
// We close this connection
$connection->close();
}
/**
* Function to send the message
* @method send_message
* @param array $user User to send
* @param array $message Message
* @param array $client Sender
* @return string
* @author Romain galLIEN <romaingallien.rg@gmail.com>
*/
protected function send_message($user = array(),$message = array(),$client = array())
{
// Send the message
$user->send($message);
// We have to check if event callback must be called
if (!empty($this->CI->ratchet_client->callback['event'])) {
// At this moment we have to check if we have authent callback defined
call_user_func_array($this->CI->ratchet_client->callback['event'],array((valid_json($message) ? json_decode($message) : $message)));
// Output
if ($this->CI->ratchet_client->debug) {
output('info','Callback event "' . $this->CI->ratchet_client->callback['event'][1] . '" called');
}
}
// Output
if ($this->CI->ratchet_client->debug) {
output('info','Client (' . $client->resourceId . ') send \'' . $message . '\' to (' . $user->resourceId . ')');
}
}
}
解决方法
这是一个非常愚蠢的错误,因为我正在检查
if (empty($auth) or !is_integer($auth))
我的 is_integer($auth)
失败了,所以我在 if 语句之前添加了 $auth=(int)$auth;
并且问题解决了...