I'm working on a small project with PHP-Websocket.
The Server side is running with this https://github.com/ghedipunk/PHP-Websockets
Server side:
require "PHP-Websockets/websockets.php";
class Server extends WebSocketServer
{
private $_connecting = 'Connecting..';
private $_welcome = 'SOCKET SERVER!';
protected function connected($user)
{
// Send welcome message to user when connected
}
protected function process($user, $message)
{
// data sent from client
$json = json_decode($message);
//prepare data response to client
$response = json_encode(array('type'=>'notify', 'message'=>'Client'.$user->id.' has sent a request.'));
$this->send($user, $response);
}
protected function closed($user)
{
// Alert on server
echo "User $user->id has closed the connection".PHP_EOL;
}
public function __destruct()
{
echo "Server Closed!".PHP_EOL;
}
}
$addr = 'localhost';
$port = '2207';
$server = new Server($addr, $port);
$server->run();
Client Side:
<script>
var uri = "ws://localhost:2207";
function socket_connect(){
socket = new WebSocket(uri);
if(!socket || socket == undefined) return false;
socket.onopen = function(){
console.log('Connected to Server!');
}
socket.onerror = function(){
console.log('Connection Failed!');
}
socket.onclose = function(){
socket_log('Connection Closed! ')
}
socket.onmessage = function(e){
//var response_data = e.data;
var msg = JSON.parse(e.data); //PHP sends Json data to client
console.log(msg.message);
var new_response = '<li>'+msg.message+'</li>;
$('#response').append(new_response);
}
}
function send_data_to_server(data){
if(!socket || socket == undefined) return false;
socket.send(JSON.stringify(data));
}
$(document).ready(function(){
socket_connect();
$('#send_request').click(function(){
send_data_to_server({message: 'Message sent from Client'});
});
});
</script>
<input type="button" id="send_request" value="Send Request to Server" />
<ul id="responses"></ul>
Everything works fine with those code above.
When Client1 sends a request to Server, the Server responses to him instantly. BUT the other clients can not see the response message.
So I want to make it go further : When a client sends a request to the server, the server will response to ALL clients so that all client can see the message.
How can I do that?
Thanks in advance && sorry for my bad English!
When a user connect, you need to add him to an array with every other users.
When one disconnect, remove him from this array.
Then when you want to send a message to every user, iterate on the array and send the message to each connected user.
WebSocketServer class has WebSocketServer::$users variable.
If you iterate over WebSocketServer::$users in split_packet function and then call main process it will work. In latest source code please iterate in line no-405.
//original
if ((preg_match('//u', $message)) || ($headers['opcode']==2)) {
//$this->stdout("Text msg encoded UTF-8 or Binary msg\n".$message);
$this->process($user, $message);
} else {
$this->stderr("not UTF-8\n");
}
//have to change
if ((preg_match('//u', $message)) || ($headers['opcode']==2)) {
//$this->stdout("Text msg encoded UTF-8 or Binary msg\n".$message);
foreach($this->users as $usr){
$this->process($usr, $message);
}
} else {
$this->stderr("not UTF-8\n");
}
Related
fpm library. I want to integrate pubnub and replace socket io with it, but my code does not work in localhost.
What i have done till now
i have followed this to install fpm in xampp. Did i miss something? what i can do to run it?
after installing it worked for once but again stopped working (did not change anything in code).
the code works fine on live server.but in localhost i am getting below error.
Stripped content to Error: Cannot send request to server. but found something wrong...
see below image
This is my code
"use strict";
var PHPFPM = require('node-phpfpm');
var striptags = require('striptags');
const log = require('simple-node-logger').createSimpleFileLogger(process.env.LOGDIR + '/poker-phpwrapper.log');
class PHPWrapper {
constructor(concierge) {
this.phpfpm = new PHPFPM({
host: process.env.NODE_POKER_PHP_HOST,
post: process.env.NODE_POKER_PHP_PORT,
documentRoot: process.env.NODE_POKER_PHP_DOCROOT
});
this.concierge = concierge;
this.busy = false;
}
houseKeeping(messages) {
var php = this;
php.busy = true;
this.phpfpm.run({
uri: 'server_wrapper.php',
json: {
func: "houseKeeping",
messages: messages
}
}, function (err, body, phpErrors) {
php.busy = false;
if (body.trim() == '') {
return;
}
// Check for PHP errors
if (body.includes('<br />')) {
// Get all the errors out until we've just got JSON left
body = body.substring(body.indexOf('\n[')+1);
}
if (body.charAt(0) != '[') {
console.log('Stripped content to ' + body + " but found something wrong...");
}
try {
var data = JSON.parse(body);
} catch (parseError) {
// throw("An error occurred parsing the JSON from PHP: " + parseError + "\nBody contents:\n" + body);
data = '';
}
if (data.length == 0) {
return;
}
for (var i in data) {
if (data[i][0] == 'CONTROL') {
// Server control message, execute as appropriate
switch (data[i][1]) {
case 'force_exit': php.concierge.wipeStateAndExit(); break;
case 'reset_server': php.concierge.wipeState(); break;
}
} else {
// Message for client
php.concierge.msgToClient(data[i][0], data[i][1]);
}
}
});
}
isBusy() {
return this.busy;
}
}
module.exports = PHPWrapper;
I'm trying to implement google sign-in to on my website.
I've done the steps from here Authenticate with Google.
This function executes after i have logged in to google :
function onSignIn(googleUser) {
var googleResponse = googleUser.getAuthResponse();
google_login(googleResponse, true);
};
Google_login function:
function google_login(res) {
var httpObject = getXMLHTTPObject();
var ajax_url = siteURL + 'google_login';
var params = 'token='+encodeURIComponent(res.id_token);
httpObject.open('POST', ajax_url, true);
httpObject.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
httpObject.onreadystatechange = function() {
if (httpObject.readyState == 4) {
if(httpObject.responseText == 'true') {
window.location = httpObject.responseURL;
}
else {
if(httpObject.responseText == '') {
window.location = siteURL + 'login_again';
}
else {
window.location = siteURL + 'google_login_error';
}
}
}
};
httpObject.send(params);
}
And in my model I'm using this code:
private $google_client;
function Google_model() {
parent::__construct();
$this->google_client = new Google_Client(['client_id' => 'my_client_id','client_secret' =>'my_client_secret']);
}
function check_google_user($access_token) {
$payload = $this->google_client->verifyIdToken($access_token);
if ($payload) {
return $payload;
}
return false;
}
In my controller I'm calling check_google_user function.
And here appears a strange behaviour. Sometimes when I try to login I get the payload, and sometimes not (PS: I'm trying to login with the same user in the same day). Am I doing something wrong?
EDIT:
I'm getting this error: Caught exception: Cannot handle token prior to 2017-01-25T16:20:24+0200
Solved this by commenting these lines in firebase JWT.php file:
throw new BeforeValidException(
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat)
);
This is the first time I am using sockets and started off with Ratchet but I seriously cant fit my head into it. Still tried to join together some parts from the tutorial but facing some problems. Plus I would like to know how to use autobahn.js with it. The tutorials are not clear.
My Problem
1) How to send a message to all users except the current user stating "
... joined" and the '...' has to be the ip of the user.
I tried the following but it gives me error on the terminal.
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients->attach($conn);
$this->send('new');
echo "New connection! ({$conn->remoteAddress})\n";
}
Call to undefined method MyApp\Chat::send()
2) What to do so that when a message is sent all the parties can view it including the one who is sending it (that's the way how every chat works)?
JS
var conn = new WebSocket('ws://localhost:8080');
conn.onopen = function(e) {
//console.log("Connection established!");
$("#chat_window #messages_list").append("<li class='join_disconnect'>127.0.0.1 Online</li>");
}
conn.onmessage = function(e) {
//console.log(e.data);
$("#chat_window #messages_list").append("<li class='thread'>"+e.data+"</li>");
}
conn.onclose = function(e) {
//console.log("Connection Disconnected!");
$("#chat_window #messages_list").append("<li class='join_disconnect'>127.0.0.1 Offline</li>");
};
$(document).ready(function(){
disable_button();
//EMERGENCY EXIT
$('#exit').click(function(){
window.location.replace('http://www.google.com');
});
//PREVENT BLANK INPUT
$('#msg').on('keyup', function(e){
if($(this).val().length>0){
enable_button();
}
else{
disable_button();
}
});
//SEND MESSAGE
$('#snd').click(function(){
var thread = $('#msg').val();
//console.log(thread);
//conn.send(thread);
$.ajax({
type:'POST',
url: './bin/send-message.php',
data: {msg: thread},
success: function(response){
//alert(response);
if(response!=1){
$('#msg').val('');
disable_button();
}
}
});
});
//ENABLE BUTTON
function enable_button() {
var element = document.getElementById('snd');
$(element).addClass('active');
element.style.pointerEvents = '';
}
//DISABLE BUTTON
function disable_button() {
var element = document.getElementById('snd');
$(element).removeClass('active');
element.style.pointerEvents = 'none';
}
});
I know these are a lot of questions but I really want to know how. If there are any step by step easy to learn tutorials those are also welcome.
If you are trying to change example from the tutorial at the Rachet site, than for your first problem solution is:
public function onOpen(ConnectionInterface $conn) {
// first, you are sending to all existing users message of 'new'
foreach ($this->clients as $client) {
$client->send('new');
}
// than,
// Store the new connection to send messages to later
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
}
Regarding your second question, if I get you right, you should send new messages to all connected clients, like this:
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
, $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
foreach ($this->clients as $client) {
// remove this check
// if ($from !== $client) {
// The sender is not the receiver, send to each client connected
// $client->send($msg);
// }
// just send to all
$client->send($msg);
}
}
Update: complete solution.
In the Chat.php, you need to modify some methods:
public function onOpen(ConnectionInterface $conn) {
// first, you are sending to all existing users message of 'new'
foreach ($this->clients as $client) {
$client->send('<status>' . $conn->remoteAddress . ' Online</status>'); //here we are sending a status-message
}
// than,
// Store the new connection to send messages to later
$this->clients->attach($conn);
echo "New connection! ({$conn->remoteAddress})\n";
}
public function onClose(ConnectionInterface $conn) {
// The connection is closed, remove it, as we can no longer send it messages
$this->clients->detach($conn);
//send to others clients message about disconnected user
foreach ($this->clients as $client) {
$client->send('<status>' . $conn->remoteAddress . ' Offline</status>'); //here we are sending a status-message too
}
echo "Connection {$conn->remoteAddress} has disconnected\n";
}
in your js code, modify next method:
conn.onmessage = function(e) {
//console.log(e.data);
var match = e.data.match(/^<status>(.*?)<\/status>$/i);
if (match) {
if (/\d+\.\d+\.\d+\.\d+ online/i.test(match[1])) {
messages.append('<li class="join_connect">' + match[1] + "</li>");
} else if (/\d+\.\d+\.\d+\.\d+ offline/i.test(match[1])) {
messages.append('<li class="join_disconnect">' + match[1] + "</li>");
}
} else {
messages.append('<li class="thread">' + e.data + "</li>");
}
};
I have an AngularJS app which has a mailer script written in PHP. I'm trying to refer to the PHP file via the angular $http service but I keep getting a 404 error when I try to use it via my contact form, in the corresponding controller, like so:
angular.module('myModule')
.controller('contactUsController', ['$scope', '$http', function ($scope, $http) {
$scope.formData = {};
$scope.submitted = false;
$scope.submit = function(contactform) {
console.log('Form data', $scope.formData);
$scope.submitted = false;
$scope.submitButtonDisabled = true;
if (contactform.$valid) {
$http({
method : 'POST',
url : "app/process.php",
data : $.param($scope.formData),
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function(data){
console.log(data);
if (!data.success) {
// if not successful, bind errors to error variables
$scope.errorName = data.errors.name;
$scope.errorEmail = data.errors.email;
$scope.errorTextarea = data.errors.message;
$scope.submissionMessage = "Sorry. Error sending message. Please try again.";
$scope.submission = true; //shows the error message
} else {
// if successful, bind success message to message
$scope.formData = {}; // form fields are emptied with this line
$scope.submissionMessage = "Thank you! Your message has been sent successfully.";
$scope.submitted = true; //shows the success message
}
});
} else {
}
}
}]);
So each time I invoke the submit() function by pressing the send button, the browser complains like so:
I've been searching around for an answer, but I haven't found one that could help me out.
I am using npm start to run my app. My project structure is as shown in the image below:
Any idea what could be going wrong? Any help is appreciated.
I just was wondering what you guys could recommend / suggest for an approach I am trying to take. I am trying to make my own simple Live Support chat system and need to make a feature for the Client to view when the Agent is typing a message. I've figured out how to do it for the person typing themselves but not for a remote person.
Please help as I am not very great at jQuery! Heres my current code that simply shows when you are typing in a input field with id of #chatMessage. Please note, this is a PHP, MySQL & jQuery chat system.
$('#chatMessage').keyup(function(){
if ($("#chatMessage").val() == ''){
$('#typing').html('');
}else{
$('#typing').html('The agent is typing a message..');
}
});
Thanks
You only need to add an ajax call to the server and then a timer on the client that checks for agent status...
// Agent side..
function checkStatus(){
jQuery.get('/server-url?agent_id=32&status', function(data){
if (data.status == 'typing')
$('#typing').html('The user/client is typing a message..');
else
$('#typing').html('');
checkStatus();
});
}
// Start the function begining.
setTimeout(checkStatus, 300);
var agent_timer;
$('#chatMessage').keyup(function(){
if (agent_timer)
clearTimeout(agent_timer);
if ($("#chatMessage").val() == ''){
status = 'empty';
} else {
status = 'writing';
}
agent_timer = setTimeout(function(){
// Send status to server php script
$.post('/server-url?agent_id=23', {status: status}, function(data){
// handle response
});
}, 400);
});
// Server side...
// check for agent, and other things...
if (isset($_GET['agent_id'])){
// Agent server side
if (isset($_POST['status']){
// Save status to database
$this->save(array('agent' => $agent, 'chat_id' => $chat_id, 'status' => $_POST['status']));
}
if (isset($_GET['status'])){
$data = $this->read(array('agent_id' => $chat_id));
}
} else {
// This is the client server side
if (isset($_GET['status'])) {
$data = $this->read(array('chat_id' => $chat_id));
return $data['status'];
}
}
// handle other things and return data if necessary
// echo json_encode($data);
// Client side JS
function checkStatus(){
jQuery.get('/server-url?chat_id=32&status', function(data){
if (data.status == 'typing')
$('#typing').html('The agent is typing a message..');
else
$('#typing').html('');
checkStatus();
});
}
// Start the function at begining.
setTimeout(checkStatus, 300);
// We can do the same, so the agent can know if user is typing too (you must also copy the above function)
var client_timer;
$('#chatMessage').keyup(function(){
if (client_timer) clearTimeout(client_timer);
if ($("#chatMessage").val() == ''){
status = 'empty';
} else {
status = 'writing';
}
client_timer = setTimeout(function(){
// Send status to server php script
$.post('/server-url?chat_id=23', {status: status}, function(data){
// handle response
});
}, 400);
});
Maybe there are better ways than updating a row in mysql... but I can't think one now..