Client not receiving message from server - javascript

Hi i have a node js server and im using sockets to communicate.
Index:
<script src="socket.io/socket.io.js"></script>
Client JS:
var socket = io.connect("http://localhost:8081");
socket.on('hi', function(data){
console.log("g");
console.log(data);
});
So it seems to connect just fine to the server. I have a socket called 'hi' waiting for any incoming messages. I added 2 console logs incase data was null, it would still print something to the console.
Server:
var express = require("express");
var app = express();
var server = require("http").Server(app);
var io = require("socket.io")(server);
var mazeGenerator = require("generate-maze");
app.use(express.static("public"));
io.on("connection", function(socket) { // EDITED
console.log("A player has connected - sending maze data...");
socket.emit("hi", "hi");
});
So when i refresh the page, the client connects and in my CMD i see the "A player has connected..." console log. From then on, its blank from the server or client, I can keep refreshing and it will keep saying a player has connected by the clients console stays blank

Since the connection is proven to be established, I suspect this is an issue of a way you emit the data. Your second parameter hi may not be taken as a data to be transmitted, according to
https://socket.io/docs/server-api/#socket-emit-eventname-args-ack
In my understanding, socket.io emit Object instead of String so can you try this?
io.on("connection", function(socket) {
console.log("A player has connected - sending maze data...");
socket.emit("hi", {data: "hi"});
});

Related

How to use socket.io to display realtime data in the client (web browser) from the node.js server?

I want to display the real-time speech to text data in the browser. By real-time what I mean is, "while I am speaking I am getting the text output simultaneously". I have implemented the speech-to-text part in Python using the Google cloud service API. Then I used "child process" to run my python program in the node.js environment. Till now everything is fine. Next, I want to display the real-time text in the browser. In another word, I want to send the real-time text output from the python (which is now running in node.js using the child process) to the web browser. I was trying to do that with socket.io. Here is my server side (node.js) code where socket.io is also applied:
const express = require('express');
//const router = express.Router();
const {spawn} = require('child_process');
const path = require('path');
const app = express();
const http = require('http');
const server = http.createServer(app);
//const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
function runScript(){
return spawn('python3', [
"-u",
path.join(__dirname, 'script.py')
]);
}
const subprocess = runScript()
// print output of the script
app.get('/', (req,res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
});
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
Above, I am first using the child process to call the python program in node.js and then I am using socket.broadcast.emit to send the text output of the python program to my client side. The client-side code looks like this:
<!DOCTYPE html>
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var messages = document.getElementById('messages');
//const EventEmitter = require('events');
//const emitter = new EventEmitter()
//emitter.setMaxListeners(50)
socket.on('messages', function(data) {
document.querySelector("#style1".innerHTML = `<p>${data1}</p>`
});
</script>
</head>
<body id="messages">
<h1> This is crazy </h1>
<div id="style1">
</div>
</body>
</html>
Above, I want to display the real-time text output from the python program inside the <p> tag.
The problem is, I am not able to get anything in the web browser.
My objective is, I want to display whatever I am speaking as text in the web browser in real-time.
I don't know much about socket.io. In fact, this is the first time I am using this technology.
Your Node.js server will act as the socket server. As your code shows, it listens on a port for a socket connection, and on connection, creates a socket, which you then send messages too. From a simple cursory review, the server code looks okay.
On your webpage, you are creating the socket, and listening for messages.
However the socket running on the webpage hasn't yet connected to the server, which is why nothing is working yet.
Assuming you're doing this on localhost, just add the socket server address to it's constructor, and then listen for connect.
const socket = io('ws://localhost:3000');
socket.on('connect', () => {
// do any authentication or handshaking here.
console.log('socket connected');
});
More advanced implementations should gracefully handle closing sockets.
Per the following comment:
I added the lines you suggested above. Even now nothing is visible on the webpage but I am getting this warning: (node:14016) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 message listeners added. Use emitter.setMaxListeners() to increase limit
Looking more closely at your server code, I believe this is the root issue
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
});
});
Each time you receive data from subprocess.stdout, you are adding a new onmessage event handler to your socket, so after a period of time, you have added too many event handlers.
Re-write your logic so that you only add socket.on('message') once (usually after your create the socket).
It is also worth noting that in the above code, data from stdout is not being used, as that data variable is being redefined in a lower scope by your onmessage function. Since data is being redefined, the output of your Python program is being ignored.
I think this is what you want:
//echo any message you receive from the socket back to the socket
socket.on('message', (data) => {
socket.broadcast.emit('message', data);
});
//send data from std out to the socket.
subprocess.stdout.on('data', (data) => {
//console.log(`data:${data}`);
socket.broadcast.emit('message', data);
});

How to read response in server after sending an alert to specific user in socket.io?

I'm new to Socket.io. Here is my problem.
I want to get the real time location of Android device. So I created a simple app to get current GPS location. And Node.js server and also Angular Admin panel.
Here is my Node.js server code.
//Some import statements are missing here. Not added.
var app = require('express')();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
// Creating the socket connection.
io.sockets.on('connection', function (socket) {
socket.on('join', function (data) {
socket.join(data.id);
});
});
module.exports = function (app, express) {
var api = express.Router();
api.post('/device_location/:child_id', function (req, res) {
var child_id = req.body.child_id;
io.sockets.in(child_id).emit('new_msg', {msg: 'gps_data'}); //Sending request to registered android device.
var gps_location = ""; //Here i want to take GPS data from android client.
res.json({ type: "success", code: 200, data: gps_location }); //Then i can send the response to anyone who need that.
});
return api;
};
If this is not clear, please check this gist : https://gist.github.com/chanakaDe/123080fa5427c38c37f36afdac10be7c
First I created the socket connection. Then Android client can connect to it with unique user ID.
Then I'm sending the request to get GPS data when admin press the button from the Administration button.
io.sockets.in(child_id).emit('new_msg', {msg: 'gps_data'});
Here, child_id is the ID of android application.
Then I want to get the response from Android app and read it in server.
After reading that, I can send that to anyone asking for it.
res.json({ type: "success", code: 200, data: gps_location });
This is the normal Node.js way of sending a response.
How can we get the response to this var gps_location = ""; variable which we are getting GPS value of specific user.
Please help me on this. Tried many ways, but not good. I just need to read the response from Android client in the server and process it.
You need to emit your GPS location from Android to your server using something like :
socket.emit("gpsdata", data)
and then receive it in Node using socket.on("gpsdata", doSomething) :
io.sockets.on('connection', socket => {
socket.on("gpsdata", data => { // Receive data from one socket
io.sockets.emit('gps_location', { gps_location : data }) // Emit to everyone
})
});
https://socket.io/docs/emit-cheatsheet/

socket.io authentification not working on first connection

I have a NodeWebkit client which connects to a nodejs server using the socket.io library (JavaScript).
The client launches the connect procedure on the application start but the server does not acknoledge any connections... Though the client's socket has the connected attribute to "true".
You should know that I am using socketio-jwt to authentificate the connection.
Github: https://github.com/auth0/socketio-jwt
I know that the connection does work in a way because if I add :
io.sockets.on('connection', function(){console.log("hello");})
It prints hello !
So it seems that event though the connection is somehow made it doesn't want to do the auth part with the library, resulting in... Well... Nothing.
But that's not all !!
Because if I reboot the app (not the server) then the auth works most of the time ! It acts like a race condition... But I dont see how it could possibly be one... Every line of code is geting executed appart of the success callback of authentification.
I tried connecting to a remote server and on my localhost.
I also tried with an other library of socket auth but I've got the same probleme.
This is the server code:
var session = require('express-session');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var socketioJwt = require('socketio-jwt');
io.sockets.on('connection', socketioJwt.authorize({
secret: 'some secret',
timeout: 15000 // 15 seconds to send the authentication message
})).on('authenticated', function (socket) {
console.log('[Info]: A user connected to socket = ', socket.decoded_token);
});
});
http.listen(5000, function () {
console.log('listening on *:5000');
});
And now the client code:
this.socket = io.connect('http://' + that.hostName +':' + that.port);
var token = jwt.sign({email: "someEail", pwd: "somePwd"}, fromServerSecret);
this.socket.on('connect', function () {
that.socket.emit('authenticate', {token: token}) //send the jwt
.on('authenticated', function () {
console.log("[Info]: Socket login successfull");
})
.on('unauthorized', function (msg) {
console.log("[Warning]: Socket unauthorized: " + JSON.stringify(msg.data));
throw new Error(msg.data.type);
});
});
The server side log "A user connected to socket" is never shown.
If you have an idear ! Thanks for your time.
Why is there a 'that' on socket.emit (client)? I think you should handle it within the same instance of socket.io - using same 'this' as above

socket.io not emitting event from server to client on connection

I have a very basic setup with socket.io but am having trouble getting my server to send back a message once the connection has been established.
When a connection is established to my server, I want the server to send back a message to the client. I've tried to accomplish this with the following code:
Server
// Modules
var fs = require('fs');
var https = require('https');
// Certificate
var options = {
pfx: fs.readFileSync('<my cert>')
};
// Create Server
httpsServer = https.createServer(options);
// Create websocket
var io = require('socket.io')(httpsServer);
// Listen on a port
httpsServer.listen(4000,function() {
console.log('listening on *:4000');
});
io.on('connection', function(socket) {
console.log('a user connected');
socket.emit('test','you connected');
});
Client
var socket = io('https://<my server>:4000');
When I execute this code, the websocket gets established and my server console shows the message "a user connected". However, the message ['test','you connected'] does not get emitted through the socket.
The only way I've been able to get this to work is to use setTimeout() to wait 500ms before emitting the event, in which case it does work.
Why is that? How can I configure my server to automatically respond with a message as soon as the user connects?
You need to listen to the emitted event, using socket.on(event, callback);
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
var socket = io('https://localhost:4000');
//test is the emitted event.
socket.on("test", function(data){
console.log(data); //"you connected"
});
</script>

using Socket.io with iOS via the socket.io Swift client

I've been trying to do basic communication between an app and my server but no matter what I do I can't seem to get it to work.
Below is my js code
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
console.log('a user connected');
io.emit("hello");
socket.on('disconnect', function() {
console.log('a user disconnected');
});
socket.on('response', function(message){
console.log(message);
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
This should in theory be alerted when a user connects, output a message saying the user has connected and then emit an event "hello"
below the on disconnect part I am trying to communicate with the server from my iOS app. I emit a event called "response" with a string called "I got your response".
I get the "a user connected" message in the console but the message I send from the iOS app never gets printed in the console.
This the code in my app.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let socket = SocketIOClient(socketURL: "192.168.0.3:3000")
socket.on("hello") {data, ack in
socket.emit("response", "I got your response")
}
socket.connect()
}
As you can see my server side code emits the event "hello". This should trigger the socket.on("hello") and make the app emit the event "response" which makes the server print out the string sent with it.
None of this is happening apart from the message that gets printed in the console when a user connects.
An help would be greatly appreciated.
the Github repo for the framework is below
https://github.com/socketio/socket.io-client-swift
Declare and initiate your socket variable in the top of the class. As previous comments said, I think the variable is lost in the scope otherwise.
class HostSocketHandler {
let socket = SocketIOClient(socketURL: urlString)
init(){
socket.connect();
}
}

Categories