我是网络套接字编程的新手。我正在 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
但是当我加载 html 时,它会在终端上显示以下内容
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, $message, $client);
} else {
// Broadcast to everybody except us
if ($client !== $user) {
$this->send_message($user, $message, $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 . ')');
}
}
}
答案 0 :(得分:0)
这是一个非常愚蠢的错误,因为我正在检查
if (empty($auth) or !is_integer($auth))
我的 is_integer($auth)
失败了,所以我在 if 语句之前添加了 $auth=(int)$auth;
并且问题解决了...