一般来说,我在套接字上编写聊天,或者更确切地说,我尝试使用棘轮为套接字进行。而且问题是发送消息时什么都没有发生,很可能是socket端的onMessage方法不起作用。这是js代码:
let websocketServerLocation = 'ws://localhost:9095/web-chat'; //название экшена должен совпадать с route в запускаемом через консоль экшене
let chat = null;
function socketStart(websocketServerLocation) {
chat = new WebSocket(websocketServerLocation);
chat.onmessage = function(e) {
let response = JSON.parse(e.data);
console.log(response);
};
chat.onerror = function(e) {
console.warn('Возникла ошибка');
chat.close();
};
chat.onclose = function() {
console.warn('Попытка подключения...');
setTimeout(function() {
socketStart(websocketServerLocation)
}, 5000);
};
chat.onopen = function(e) {
console.log('Вы онлайн');
};
$('.new-message-form').submit(function (e) {
e.preventDefault();
let text = $('#textMessage').val();
let only = 0;
if ($('#onlyForAdmin').prop('checked') === true) {
only = 1;
}
//
$('#textMessage').val();
$('#onlyForAdmin').prop('checked', false);
let message = { id: chat_id, guid: chatGuid, web_id: webinarID, name: currentName, type: 0, only: only,
time: new Date(), text: text };
console.log(message);
if (chat.readyState === chat.OPEN) {
// Если соедение не открыто
chat.send(message);
addMessage(message);
} else {
console.warn('WS NOT CONNECTED');
}
});
}
这个函数的启动在代码下面,但是因为 太大了,我就不放了。这是套接字代码:
class Chat implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new SplObjectStorage();
}
public function onOpen (ConnectionInterface $conn) {
// Сохраните новое соединение для отправки сообщений позже
$this->clients->attach($conn);
echo "New connection: " . $conn->resourceId . "\n";
}
public function onMessage (ConnectionInterface $from, $msg) {
Yii::info($from);
$current_client = $this->findConnection($from);
Yii::info($current_client);
$request = json_decode($msg, true);
$result = null;
Yii::info($request);
if (!empty($request['text']) && $message = trim($request['text'])) {
// Здесь можно сохранять сообщения в БД
$saved_message = Dialogs::saveMessage($request['id'], $request['guid'], $request['web_id'],
$request['name'], $request['type'], $request['only'], $request['time'], $message);
$result = $saved_message;
if ($result !== null) {
foreach ($this->clients as $client) {
// if ($from != $client) {
$client->send(json_encode([
'from' => $current_client->name,
'date' => date( 'H:i', $result->created_at ),
'message' => $message,
]));
// }
}
} else {
// Выводит сообщение если при сохранении возникли ошибки
$result = $saved_message;
}
}
$from->send(json_encode($result));
}
public function onClose (ConnectionInterface $conn) {
// Соединение закрыто, удалите его, так как мы больше не можем отправлять ему сообщения.
$this->clients->detach($conn);
echo "Connection " . $conn->resourceId . " has disconnected\n";
}
public function onError (ConnectionInterface $conn, \Exception $e) {
echo "Произошла ошибка: " . $e->getMessage() . "\n";
$conn->close();
}
public function findConnection( ConnectionInterface $conn ) {
// Ищем пользователя, который написал
foreach ($this->clients as $client) {
if ($client->connection === $conn) {
return $client;
}
}
return null;
}
}
如您所见,我正在尝试记录一些数据,但它没有出现在日志中。套接字调用代码:
public function actionStart() {
$app = new RatchetApp('localhost', 9095);
// $app = new App('localhost', 9095);
$app->route('/web-chat', new Chat(), ['*']);
$app->run();
}
顺便说一句,RatchetApp
创建该类是为了解决 xDebug 的错误。这是他的代码:
class RatchetApp extends App {
/**
* RatchetApp constructor.
* @param string $httpHost
* @param int $port
* @param string $address
* @param LoopInterface $loop
*/
public function __construct(string $httpHost = 'localhost', int $port = 8080, string $address = '127.0.0.1',
LoopInterface $loop = null) {
@parent::__construct($httpHost, $port, $address, $loop);
}
}
我发现了问题所在,所有内容都只需要在将消息发送到服务器之前包装在 json 中,如下所示: