Ratchet client message - javascript

I have already integrated pusher using Ratchet. Broadcasting to all users works fine.
Now I'm trying to find a way how to send a message to specific user when I got it's connection.
method which is executed on subscribe :
public function onSubscribe(ConnectionInterface $conn, $topic) {
$conn->send(json_encode("Hello"));
}
JS on client side:
var conn = new ab.Session('ws://127.0.0.1:8080',
function() {
conn.subscribe('chat', function(topic, data) {
console.log(data); // here I'd like to get that "Hello" message
});
},
function() {
console.warn('WebSocket connection closed');
},
{'skipSubprotocolCheck': true}
);
I'm not getting any message, I guess I haven't formatted it properly (json_encode("Hello")). Any help ?

You need to store the connections somehow and then call them directly.
For instance:
$conns[$conn->resourceId] = $conn;
And then later:
$conns[$resourceId]->write("new data");
As for why you're not receiving the message on subscribe, try the write() method instead of the send() method.
Also, check the console to see if you're receiving the data but not unpacking it properly.

Related

(javascript) Unable to return value received in Socket.on(event)

Basically I have a client side code that sends data to the server, the server responds with data which calls a socket.on(event) in the client side code. Within the function that is immediately run I can log the received data but I cannot return it to outside for the life of me.
function receive_data(){
socket.off('Sent_data_to_client').on('Sent_data_to_client',(player_info));
console.log(player_info)
}
If i try to log player_info it tells me it is undefined "Uncaught (in promise) ReferenceError: player_info is not defined". I want to return player_info as the result of the receive_data function but it is undefined.
I am new to javascript and Socket.Io as a whole, i apologise for any obvious mistakes made.
Sockets in JS doesnt work like this. Have a specifics events.
https://nodejs.org/api/net.html#new-netsocketoptions
This is the Node JS documentation, but it doesn't matter because Node JS is based on "V8 engine", that is, it's the same.
As you can see in the documentation it indicates that there are a series of events that the socket can handle, among them the 'data', calling a callback function where you implement the necessary logic for your code.
In this case, for example:
const net = require('net');
const socket = new net.Socket();
// Open a socket connection with example.com
socket.connect(80, 'example.com', () => {
console.log('Connected');
});
socket.on('data', (data) => {
console.log(`Recived: ${data}`);
});
socket.on('error', (error) => {
console.log(`Error: ${error}`);
});
You should change the function definition to accept an argument, which will be the data that the server sends.
function receive_data(){
socket.off('Sent_data_to_client').on('Sent_data_to_client', function(player_info) {
console.log(player_info);
return player_info;
});
}

SignalR callback does not trigger in JQuery UI widget

I am trying to create a JQuery UI widget that receives realtime updates from a server using SignalR (2.2.0). Invoking a method on the server works just fine, however invoking a client callback from the server does not trigger on the client.
I have enabled logging on the client as is suggested here: SignalR Troubleshooting and I can see in the console that the connection is setup just fine but the client method is never invoked. There is no error message of any kind. I have also defined the client method on the hub proxy before starting the connection like so:
_bindClientCallbacks: function () {
theHub.client.broadCastToClient = function (message) {
twr.log(message);
};
}
and afterwards I start the hub connection like so:
_startSignalRClient: function () {
$.connection.hub.logging = true;
$.connection.hub.start()
.done(function () {
twr.log("Connected to SignalR hub, id=" + $.connection.hub.id);
})
.fail(function () {
});
}
These methods are called in the '_create()' function in the JQuery widget like so:
_create: function () {
theHub = $.connection.DataImportHub;
this._bindClientCallbacks();
this._startSignalRClient();
}
This works fine and I can get a valid connection with an id. I can also call a server method from the client. But when I try to invoke the broadCastToClient method on the client from the server like so:
public void BroadCastToClient(string userId, string message)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<DataImportHub>();
foreach (var connectionId in _connections.GetConnections(userId))
{
hubContext.Clients.Client(connectionId).broadCastToClient(message);
}
}
Nothing happens on the client.. even though the server does find a valid connection that corresponds to the connection id I got on the client.
What am I missing here?
Just found out the solution by reading this post. Apparently having a custom SignalR dependency resolver setup in the Owin startup class breaks javascript callbacks. Moving the dependency resolver setup code to Application_Start in Global.asax does the trick. Why this happens really is beyond me...
Bad DI setup in Startup.cs
app.Map("/signalr", map =>
{
var hubConfiguration = new HubConfiguration
{
Resolver = new NinjectSignalRDependencyResolver(new StandardKernel())
};
map.RunSignalR(hubConfiguration);
});
Good DI setup in Global.asax
protected void Application_Start()
{
GlobalHost.DependencyResolver = new NinjectSignalRDependencyResolver(new StandardKernel());
}

CometD data not reaching client

I have two client applications that use CometD to talk to a server. My server sends some data to my clients using the deliver() method of the ServerSession. The data is in the form of a string.
One of my applications is a Javascript- based web application. I can access the data delivered by the server in the following manner:
function(theMsg) {
alert(theMsg.data);
}
This works well as a callback for when I want to send data on a particular channel.
Unfortunately, my second application is a Java application whose callback does not seem able to get the data. The callback works as follows:
public void onMessage(ClientSessionChannel channel, Message message)
{
String data = (String )theMsg.getData();
System.out.println("Data "+data);
}
The problem here is that the getData() for some reason returns a null in Java. I cannot seem to find any way to get at the data that I sent from the server!
Is there some kind of bug in the java CometD API, or am I using the wrong function to get the data that I am sending from the server? How can I get at this data?
Someone please advise...
Addition 1: below is the first client, implemented in Javascript, as requested by sbordet. This client works...
var cometD = $.cometd;
var isConnected = false;
var rcvHandshake = function(hndValue) {
console.log("Received handshake. Success flag is " + hndValue.successful);
}
var amConnected = function(msgConnect) {
if(cometD.isDisconnected())
{
isConnected = false;
console.log("Server connection not established!");
}
else
{
var prevconnected = mySelf.isConnected;
// This checks whether or not the connection was actually successful
isConnected = msgConnect.successful === true;
if((prevconnected == false) && (isConnected == true))
{
console.log("Connected to the server!");
cometD.addListener("/service/output",updateOutput);
}
else if((prevconnected == true) && (isConnected == false))
{
console.log("Connection to server has ended!")
}
}
}
var startUp = function() {
console.log("Starting up...");
var cometURL = $(location).attr('origin') + "/tester/cometd";
cometD.configure({
url: cometURL,
logLevel: 'info'
});
cometD.addListener('/meta/handshake',rcvHandshake);
cometD.addListener('/meta/connect',amConnected);
cometD.handshake({
"thehash.autohash": "foo-bar-baz-hash"
});
}
var updateOutput = function(theOut) {
alert(theOut.data);
}
I solved the problem.
I was looking over my Java code in order to format it for posting to this Question, when I noticed a typo in the channel names that I was listening for. I corrected the typo, which included a channel that I was using to publish requests to the server (apparently the listener I was using was activated before the data was returned), and as a result the getData() method was empty.
Sending the data to the correct channel solved the problem. My getData() method no longer returns null.
Sorry I bugged people about such a ridiculously amateurish mistake. I will try to avoid this sort of thing in future.
Special thanks to sbordet for requesting the full code, which caused me to re- examine it and find my typo...

Call specific functions with Websockets?

I'm trying to deploy an app with Heroku but I guess they don't allow use of Socket.IO so I have to use basic WebSockets. How do I send data to specific functions e.g.
With sockets it would be:
// Server
socket.on('testFunction', function(data) {
console.log(data);
});
// Client
socket.emit('testFunction', 'Hello!');
But with Websockets from what I've googled all I can find is
// Server
ws.onmessage = function(data) {};
// Client
ws.send('This is a string, what do I do with myself');
Any information would be great. Thanks!
See here for some documentation and examples.
Here are some rough equivalents to your Socket.IO examples:
// Server
ws.onmessage = function(event) {
var msg = JSON.parse(event.data);
switch(msg.type) {
case "testFunction":
console.log(msg.text);
break;
}
};
// Client
ws.send(JSON.stringify({type: "testFunction", text: "Hello!"}));
The solution to your problem depends on your server side code.
The way i solved the function calling problem, is by sending my data to server as an object( stringified), containing controller and action properties.
e.g in pseudo code
var request = {controller: "users", action: "login", params: {username: "loginuser", password: "333"} };
socket.emit(JSON.stringify( request) );
and on server side i get the controller value, and instantiate a new controller based on it...eg new users_controller(), and call the action on that controller with the params sent from emit.
Of course you need to test if controllers and actions exists, handle errors etc.

How to be sure that message via socket.io has been received to the client?

How to check that message sent with socket.io library has been received to the client.
Is there special method for it in socket.io?
Thanks for your answers!
You should use the callback parameter while defining the event handler.
A typical implementation would be as follows:
Client side
var socket = io.connect('http://localhost');
socket.emit('set', 'is_it_ok', function (response) {
console.log(response);
});
Server side
io.sockets.on('connection', function (socket) {
socket.on('set', function (status, callback) {
console.log(status);
callback('ok');
});
});
Now check the console on the server side. It should display 'is_it_ok'. Next check console on client side. It should display 'ok'. That's the confirmation message.
Update
A socket.io connection is essentially persistent. The following in-built functions let you take action based on the state of the connection.
socket.on('disconnect', function() {} ); // wait for reconnect
socket.on('reconnect', function() {} ); // connection restored
socket.on('reconnecting', function(nextRetry) {} ); //trying to reconnect
socket.on('reconnect_failed', function() { console.log("Reconnect failed"); });
Using the callback option shown above is effectively a combination of the following two steps:
socket.emit('callback', 'ok') // happens immediately
and on the client side
socket.on('callback', function(data) {
console.log(data);
});
So you don't need to use a timer. The callback runs immediately except if the connection has any of the following states - 'disconnect', 'reconnecting', 'reconnect_failed'.
You can use the socket.io's acknowledgements.
Quote from the socket.io documentation:
Sometimes, you might want to get a callback when the client confirmed
the message reception.
To do this, simply pass a function as the last parameter of .send or
.emit. What's more, when you use .emit, the acknowledgement is
done by you, which means you can also pass data along.
On the client side simply emit the event with your data, the function will be called whenever the server responds to your event:
client.emit("someEvent", {property:value}, function (data) {
if (data.error)
console.log('Something went wrong on the server');
if (data.ok)
console.log('Event was processed successfully');
});
On the server side you get called with the data and the callback handle to send the response:
socket.on('someEvent', function (data, callback) {
// do some work with the data
if (err) {
callback({error:'someErrorCode', msg:'Some message'});
return;
}
callback({ok:true});
});
When you add a function as the last parameter of .send() or .emit() method calls, this function is called when the other party receives the message.
socket.send('hi', function() {
// if we are here, our salutation has been received by the other party.
});

Categories

Resources