The following is a unit test to show the behavior that I'm experiencing, which I recognize as different than what I've experienced before. In essence, the way I was using sockets before (maybe two months ago) stopped working sometime between then and now. I'm not sure what happened. My previously working code has broken.
var socketio = require('socket.io');
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type' : 'text/html' });
var html = "<html><head><script src=\"/socket.io/socket.io.js\"></script>\
<script>var sock = io.connect();\
sock.on('sup', function(data) {\
console.log(\"whoo\");\
sock.emit('howdy', {'hi' : 'ho'});\
});</script></head></html>";
res.end(html);
}).listen(8080);
socketio.listen(server, {log:false}).on('connection', function(socket) {
socket.on('howdy', function(data){console.log("HI!");});
socket.emit("sup", {"hey" :"yo"});
});
What I would expect from the code is the following sequence of events:
socket connects, server emits "sup" message.
client receives "sup" message and logs "whoo"
client sends "howdy" message
server receives "howdy" message and logs "HI!"
Step 4 is not occurring at all. (and therefore I assume step 3 might not be happening, either)
What's going on?
Your client side code is essentially this
var sock = io.connect();
console.log("Gets here");
sock.on('sup', function(data) {
console.log("whoo");
});
sock.emit('howdy', {'hi' : 'ho'});
I'm assuming it will work if you just move the emit into the handler.
var sock = io.connect();
console.log("Gets here");
sock.on('sup', function(data) {
console.log("whoo");
sock.emit('howdy', {'hi' : 'ho'});
});
Or you can try listening for the connect event
var sock = io.connect();
console.log("Gets here");
sock.on('sup', function(data) {
console.log("whoo");
});
sock.on('connect', function() {
sock.emit('howdy', {'hi' : 'ho'});
});
I just updated socket.io, and it's working now.
Related
I'm trying to build a chat application using Laravel, with node js server, socketio and redis. What I have is this:
Client JS:
var socket = io('http://localhost:3005');
var room = '17';
$("#send").click(function(){
content = $("textarea").val();
id =$("#id").val();
$.ajax({
url: "{{route('send.message')}}",
method: "POST",
data: {content, id, room},
success: function(){
}
});
});
socket.on('cacad', function(message){
console.log(message); //multiple copies here
});
socket.on('connect', function(){
console.log("Connected!");
socket.emit('room', room);
});
Laravel Controller:
public function sendMessage(Request $request){
event(new EventName($request->all()));
$message = new Message;
$message->message = $request->content;
$redis = LRedis::connection();
$redis->publish('chat-channel', json_encode($request->all()));
$message->save();
}
Node Server:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var redis = require('ioredis');
var myMessage;
var redis_client = redis.createClient();
redis_client.subscribe('chat-channel');
io.on('connection', function(socket) {
redis_client.on('message', function(channel, message) {
var myData = JSON.parse(message);
socket.broadcast.to('17').emit('cacad', 'u i u a a');
});
socket.on('room', function(room){
socket.join(room);
});
socket.on('disconnect', function(){
console.log("disconnected!");
});
});
http.listen(3005, function() {
console.log('Listening on Port 3005');
});
I am trying to broadcast a message u i u a a in room 17. But when I receive it in the console, it shows multiple copies of it, 2x-4x. In the Laravel controller I publish a message using redis and I subscribe to it in node server. It is received successfully, but the problem lies with the multiple copies of the message (client side).
Please where is it wrong? Thank you :)
I'm pretty convinced I found the issue although I had to search a bit about those simple API usage because I'm not using the library lately.
Looking at the docs it's explain your issue pretty clearly.
Here you are listening to a new connection,
io.on('connection', function(socket) {
If the client asked to join to a specific room, you join him:
socket.on('room', function(room){
socket.join(room);
So far it's like the docs:
io.on('connection', function(socket){
socket.join('some room');
});
But your issue is with your emit, on each client connection, you listen to a message from your redis. Then you broadcast it to the room with an emit of the connected client.
Instead of that, you can do this:
io.on('connection', function(socket) {
socket.on('room', function(room){
socket.join(room);
});
socket.on('disconnect', function(){
console.log("disconnected!");
});
});
redis_client.on('message', function(channel, message) {
var myData = JSON.parse(message);
io.to('17').emit('cacad', 'u i u a a');
});
I think this happens on the socket-io-client side. not on the server-side. when I was using react-js for the client-side. I received the same message multiple times.
with the same server, I imported socket-io-client 4.4.1 in the vanilla js front-end project. then I didn't get multiple messages... :)
try use latest socket io client versions. i think they have fixed the issue in the latest versions..
I found lot of samples in here, but very old posts using very old node and adobe air versions. I made simple node js server which is working properly - tested with web browser. Node JS is version 6.11.
var http = require('http');
var sockets = [];
var server = http.createServer(function(req, res) {});
server.listen(8080);
var io = require('socket.io').listen(server);
io.set('transports', ['websocket','flashsocket']);
io.sockets.on('connection', function (socket) {
sockets.push(socket);
socket.on('disconnect', function() {
var i = sockets.indexOf(socket);
sockets.splice(i, 1);
});
socket.on("data",function(d){
console.log('data from flash: ',d);
});
socket.write(JSON.stringify({message:"blah blah"}));
});
My task is to connect it to AS3 Air application. Script looks something like this:
public class CustomSocket extends Socket {
public function CustomSocket(host:String = null, port:uint = 0) {
super();
configureListeners();
if (host && port) {
super.connect(host, port);
}
}
private function configureListeners():void {
addEventListener(Event.CLOSE, closeHandler);
addEventListener(Event.CONNECT, connectHandler);
addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
}
....
}
It is connecting to socket with no error, but neither sending or receiving data are working. Only connecting event is fired and that's it. ProgressEvent.SOCKET_DATA is never fired. Also, on connect I send some data to node, never received.
Any idea?
Figured it out. Instead of using socket.io, like for web pages, I had to use TCP socket connection on nodejs side. When I create script like this:
var net = require('net');
var net_server = net.createServer(function(socket) {
socket.write('blah blah \n');
socket.on('data', function(chunk) {
});
socket.on('error', function(err) {});
});
net_server.listen(8000);
there is bi-directional communication which is working.
I am having a problem of using socket IO to connect my server to the client(http website).
On the client, I have a button that when pressed, sends data to the server. However, this only works with one client.
If I have two clients, the first person to open the http website gets the socket IO connection, while the second person can open the page, but can't send any data to the server.
On the client side:
var socket = new io.connect('ServerIP:8090');
socket.on('message', function(obj){
if ('buffer' in obj){
//ignore this
} else message(obj);
});
On server side:
var io = io.listen(server)
, buffer = [];
io.on('connection', function(client)
{
client.send({ buffer: buffer });
client.broadcast.send({ announcement: client.sessionId + ' connected' });
chatGuests.push(client);
client.on('message', function(message){
var msg = { message: [client.sessionId, message] };
buffer.push(msg);
if (buffer.length > 15) buffer.shift();
client.broadcast.send(msg);
});
client.on('disconnect', function(){
client.broadcast.send({ announcement: client.sessionId + ' disconnected' });
});
Instead of using client.broadcast.send(something) and client.send(something) use io.emit('eventName', something). Also, for setting up the server with the variable io use
var socket = require('socket.io');
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app);
var io = socket.listen(server);
And then after your code:
server.listen(8090);
This allows you to use the node.js module express, which allows additional communication between the client and server (but doesn't require you to rewrite your socket.io code).
For your client code, instead of using:
socket.on('message', function(obj){
//Do something
});
Use:
socket.on('eventName', function(something){
//Do something
});
This works for multiple kinds of data passing, not just messages. You can multiple event listeners to each do different things
It is simple chat app using node.js and socket.io. This app work fine in my local computer but do not work when I upload it to the server: Please look at my code on remote server and the problem.
Here is the code snippet of client:
<script type="application/javascript">
var socket = io.connect();
eventHandler(socket);
function eventHandler(socket) {
socket.on('connect', function(){
socket.emit('adduser', prompt("What's your name?"));
});
socket.on('error', function () {
console.log("Connection error"); //It works after a few second with error
});
}
$(document).ready(function(){
.....
});
</script>
It looks like on the remote server Socket.IO 0.9.16 is installed (which is not up-to-date). If you're writing code according to new documentation this might be a reason why it doesn't work as you expected.
Try to upgrade Socket.IO to 1.0
This change worked for me:
you wrote this method:
var socket = io.connect();
Thanks to another help page, I switched this method to this:
var socket = io.connect('http://localhost:8080');
You can replace "localhost" with whatever ip address you use to access your server.
Also, just in case - if you haven't, it would be useful to include a connection notification on your server in the app.js file. mine looks like the following:
var fs = require("fs")
, http = require("http")
, socketio = require("socket.io");
var server = http.createServer(function(req, res) {
res.writeHead(200, { "Content-type": "text/html"});
res.end(fs.readFileSync(__dirname + "/index.php"));
}).listen(8080, function() {
console.log("Listening at http://localhost:8080");
});
socketio.listen(server).on("connection", function(socket) {
console.log("CONNECTED");
socket.on("message", function(msg) {
console.log("Message received: ", msg);
socket.broadcast.emit("message", msg);
});
});
You can also see the help page I linked to in case they have something that more closely relates to your issue.
Your page seems to be working for me. Make sure your page is fully loaded before executing your script. This is done by using window.onload like this:
<script>
window.onload = function() {
//Your code here
}
</script>
Here's my problem:
I have server A, running node.js and using socket.io for communicating with clients (web browsers). This all is running fine and dandy.
However, now that I have server B, which also needs to connect to server A through websockets, I have hit a wall. None of the node.js websocket clients I've found won't work with the socket.io on the server A.
So, this is the case I'm striving for:
.--------. .----------. .----------.
| CLIENT | <--> | SERVER A | <--> | SERVER B |
'--------' '----------' '----------'
Client-server A connection is done through socket.io
Now, Server B (running node.js) should connect to server A via websocket (in order to go through port 80). But...
Even the example code in socket.io-client module doesn't work... :/
// Connect to server
var socket = new io.Socket('localhost', {port: 8080});
socket.connect();
// Add a connect listener
socket.on('connect', function(socket) {
console.log('Connected.');
});
The code just passes without any errors and execution ends after few seconds.
Update: Code samples
Server (which works just fine) looks like this:
// Load requirements
var http = require('http'),
io = require('socket.io');
// Create server & socket
var server = http.createServer(function(req, res){
// Send HTML headers and message
res.writeHead(404, {'Content-Type': 'text/html'});
res.end('<h1>Aw, snap! 404</h1>');
});
server.listen(8080);
io = io.listen(server);
// Add a connect listener
io.sockets.on('connection', function(socket) {
console.log('Client connected.');
// Disconnect listener
socket.on('disconnect', function() {
console.log('Client disconnected.');
});
});
Client looks like this
console.log('1');
// Connect to server
var io = require('socket.io-client')
var socket = new io.Socket('localhost', {port: 8080});
socket.connect();
console.log('2');
// Add a connect listener
socket.on('connect', function(socket) {
console.log('Connected!');
});
console.log('3');
1, 2 and 3 prints out just fine, no errors, and few seconds later the process just exits
Also, server A doesn't output anything to the log, even though I have the socket.io logging set on "everything".
For future people:
Here is 2 very simple Node.js apps that use socket.io to connect, send and receive messages between each other.
Required package is:
npm install socket.io
Node-App-1 server.js:
var io = require('socket.io').listen(3000);
io.on('connection', function (socket) {
console.log('connected:', socket.client.id);
socket.on('serverEvent', function (data) {
console.log('new message from client:', data);
});
setInterval(function () {
socket.emit('clientEvent', Math.random());
console.log('message sent to the clients');
}, 3000);
});
Node-App-2 client.js:
var io = require('socket.io-client');
var socket = io.connect("http://localhost:3000/", {
reconnection: true
});
socket.on('connect', function () {
console.log('connected to localhost:3000');
socket.on('clientEvent', function (data) {
console.log('message from the server:', data);
socket.emit('serverEvent', "thanks server! for sending '" + data + "'");
});
});
Turns out I was using old examples, for some reason, even though I triple checked them. Well, doh.
Also, it turned out that the socket.io-client is broken on latest Node (6.x.x). Managed to find an update from github for it, replaced the files and yay, everything's working!
Edit: Unfortunately I didn't save any links to working examples but after quickly skimming through the code it seems that the only changes were to the client code, which now looks like this:
console.log('1');
// Connect to server
var io = require('socket.io-client')
var socket = io.connect('localhost:8080', {reconnect: true});
console.log('2');
// Add a connect listener
socket.on('connect', function(socket) {
console.log('Connected!');
});
console.log('3');
Here is a snippet of code I wrote, it's using socket.io 1.0.6 and socket.io-client 1.0.6. The case is the following:
Server A (Socket.io Client) <---> Server B (Socket.io Server)
Server B (Server):
// Load requirements
var http = require('http'),
io = require('socket.io');
// Create server & socket
var server = http.createServer(function(req, res)
{
// Send HTML headers and message
res.writeHead(404, {'Content-Type': 'text/html'});
res.end('<h1>Aw, snap! 404</h1>');
});
server.listen(8080);
io = io.listen(server);
// Add a connect listener
io.sockets.on('connection', function(socket)
{
console.log('Client connected.');
// Disconnect listener
socket.on('disconnect', function() {
console.log('Client disconnected.');
});
});
Server A (Client):
console.log('1');
// Connect to server
var io = require('socket.io-client');
var socket = io.connect('http://localhost:8080', {reconnect: true});
console.log('2');
// Add a connect listener
socket.on('connect', function(socket) {
console.log('Connected!');
});
console.log('3');
If I'm using localhost:8080 only on the client server it doesn't connect.