I can't figure out why my socket.io server isn't receiving messages from the client. Here is my server JS file:
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');
socket.on('bid', function(msg){
console.log('received:' + msg);
});
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
And here is the client-side code:
$(function () {
var socket = io(':3000/socket.io/socket.io.js');
$('#bid-form').on('submit',function(){
socket.emit('bid', 'test');
console.log('emit');
return false;
});
});
When I open and close the browser page I see the "user connected" and "user disconnected" messages on the server console so I know it's making the connection.
When I submit the form I see the "emit" message in the browser console so I know the form submit event is firing but I'm not receiving the test message on the server. Nothing seems to happen on the client or sever end, it seems like the "socket.emit" function isn't doing anything.
What am I doing wrong?
My assumption is that you are running your express server on localhost.
It looks like you're accessing your HTML file directly through file:// unless your client-sided code is hosted by a different web server. But regardless of that, here's how you can connect:
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io("http://localhost:3000");
$('#bid-form').on('submit',function(){
socket.emit('bid', 'test');
console.log('emit');
return false;
});
});
</script>
You will need to load the socket.io.js file through the script tag. Then connect to your socket.io server by providing the host of the socket.io server to the io() function.
Related
My question is am i possible to run the socket.io lib without using express? The thing is i want to make node as an external web socket server which just receives sockets connection and callbacks and just simply reply to them, not to make own routes or send page view (I'm using codeigniter for that work).
My current test app is like this on Server:
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 4000;
server.listen(port, function() {
console.log('Server listening at port %d', port);
});
io.on("connection", function (socket) {
console.log('A new socket has joined: ' + socket.id);
var tweet = {user: "nodesource", text: "Hello, world!"};
// to make things interesting, have it send every second
var interval = setInterval(function () {
socket.emit("tweet", tweet);
}, 1000);
socket.on("disconnect", function () {
clearInterval(interval);
});
});
On Client:
<script>
const socket = io('http://localhost:4000/node_server');
socket.on('disconnect',function(){
alert('Im not connected, server is down');
});
socket.on("tweet", function(tweet) {
// todo: add the tweet as a DOM node
console.log("tweet from", tweet.username);
console.log("contents:", tweet.text);
});
My problem is that i have tested with express the chat example of socket.io and it works ofc but they use route and send the page and in my case i just want my other external page to communicate with node and not node sending me the page. Basically when i trigger some emit or function at server or client it does not fire just on server the connection but nothing else (p.s: also used io.sockets.on and doesn't work too)
If anyone has passed this and knows what my problem might be, i'll be glad.
Okay let's start off with something really basic here is our express server which is only hosting our socket application:
var app = require("express")();
var server = require("http").createServer(app);
var io = require("socket.io")(server);
var port = process.env.PORT || 4000;
server.listen(port, function() {
console.log("Server listening at port %d", port);
});
io.on("connection", function(socket) {
console.log("A new socket has joined: " + socket.id);
socket.on("hello", function(data) {
console.log(data);
});
});
You already understand that much but, it's important to note that this server will listen for any socket connections from any address. This is important to keep in mind.
Now let's look at the client html file
<html>
<body>
<button id="hiBtn">Say Hi to your server</button>
<!-- You only need to include the client file here -->
<script src="https://rawgit.com/socketio/socket.io-client/master/dist/socket.io.js" </script>
</script>
<script>
const serverLocation = "localhost:4000" // or whatever your server location is
const socket = io(serverLocation);
window.onload = function () {
document.getElementById("hiBtn").addEventListener("click", function () {
socket.emit("hello", "Hi there, this is the client speaking");
})
}
</script>
</body>
</html>
Notice how I do not have <script src="/socket/socket.io"> this is because this html file is being hosted on a completely separate client. You need to simply include the client socket.io file here which is usually located in node_modules\socket.io-client\dist\socket.io.js if you installed it via NPM. Or you can use the url I provided in my example. Just make sure that serverLocation points to your express server and you're all set.
P.S. for this example I tested it by hosting the html file on port:5000 and the express server on port:4000 if you were curious.
My problem is simple I'm actually getting an error 404 when I'm trying to import socket.io on my web page. I'm using
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
to import socket.io.
If I remove this line form my head tag, I'm fine but when it's there, I see in the dev tool the 404 error and my counter is not even working.
I am trying to make a live viewer count for one of my website but I never really use Node.js so this is why I have some trouble. Please forgive me if there is an error in my script.
For the serverside script, the file is called: viewercounter.js and this is the code
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = 8001;
server.listen(port, function () {
console.log('Server listening at port %d', port);
});
app.use(express.static(__dirname + '/public'));
var count = 0
io.on('connection', function(socket) {
count++;
socket.broadcast.emit('userupd', {
numUsers: count
});
console.log(count);
socket.on('disconnect', function(){
count--;
socket.broadcast.emit('userupd', {
numUsers: count
});
console.log(count);
});
});
Then I placed the clientside script directly in my page instead of making a new file, I did not really see the point of it. Anyway, the file is called: index.php
and the code is at the end of the file just before the end of the body tag and there not other js before the code.
<script type="text/javascript">
$(function() {
var socket = io();
socket.on('userupd', function (data) {
$('.counter').html(data);
});
});
EDIT
By looking more deeper, I've been able to understand that it's a XMLHttpRequest problem. In fact, when the socket.io code that I just imported try to perform xhr.send(this.data) the error appears. Anyone knows how I can solve this ?
https://gyazo.com/53f64081a92b449e157df76c6c570178
EDIT2
After changing the port in the file viewcounter.js. It looks like this:
// Setup basic express server
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = 80;
server.listen(port, function () {
console.log('Server listening at port %d', port);
});
// Routing
app.use(express.static(__dirname + '/public'));
var count = 0
io.on('connection', function(socket) {
count++;
socket.broadcast.emit('userupd', {
numUsers: count
});
console.log('New user: ');
socket.on('disconnect', function(){
count--;
socket.broadcast.emit('userupd', {
numUsers: count
});
console.log('Neg user:');
});
});
If your web page is coming from an Apache web server on port 80 and you want to create a socket.io server in node.js on the same host, then you need to pick a new port for that socket.io server and when you connect to the socket.io server, you need to identify the port you want to connect to because the default will be port 80, but that's not where your socket.io server is.
I'd suggest using port 8001 like you originally had for your socket.io server. Please change your node.js code back to that.
Then, you can change the socket.io code in your page from this:
<script type="text/javascript">
$(function() {
var socket = io();
socket.on('userupd', function (data) {
$('.counter').html(data);
});
});
</script>
to this:
<script type="text/javascript">
$(function() {
var url = window.location.protocol + "//" + window.location.hostname + ":8001";
var socket = io(url, {transports: ['websocket'], upgrade: false});
socket.on('userupd', function (data) {
$('.counter').html(data);
});
});
</script>
This will connect socket.io to the same protocol and host as your web page, but a different port and it will use only a webSocket so you don't run into cross origin issues with socket.io's usual attempt to initiate a connection with Ajax polling.
If your socket.io server is actually on a different host than your Apache server, then you need to put that host in the URL rather than window.location.hostname.
So I'm trying to broadcast Laravel 5 Events with the help of Redis. No I don't wanna use a service like Pusher since it's not free (even if the free limit would be enough for me) and I wanna keep control of the broadcast server.
So what I've done so far is, I'Ve set up a redis server (listening on port 6379 -> default), I've set up the following event:
class MyEventNameHere extends Event implements ShouldBroadcast
{
use SerializesModels;
public $data;
/**
* Create a new event instance.
*
* #return \App\Events\MyEventNameHere
*/
public function __construct()
{
$this->data = [
'power' => 10
];
}
/**
* Get the channels the event should be broadcast on.
*
* #return array
*/
public function broadcastOn()
{
return ['pmessage'];
}
}
I registered a route to that event:
Route::get('test',function()
{
event(new App\Events\MyEventNameHere());
return "event fired";
});
I've created (more like copied :P) the node socket server:
var app = require('http').createServer(handler);
var io = require('socket.io')(app, {origins:'*:*'});
var Redis = require('ioredis');
var redis = new Redis();
app.listen(6379, function() {
console.log('Server is running!');
});
function handler(req, res) {
res.writeHead(200);
res.end('');
}
io.on('connection', function(socket) {
console.log(socket);
});
redis.psubscribe('*', function(err, count) {
});
redis.on('pmessage', function(subscribed, channel, message) {
console.log(message);
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
And I created the view to actually receive the broadcast (testview.blade.php):
#extends('layout')
#section('content')
<p id="power">0</p>
<script>
var socket = io('http://localhost:6379');
socket.on("pmessage:App\\Events\\MyEventNameHere", function(message) {
console.log(message);
$('#power').text(message.data);
});
console.log(socket.connected);
</script>
#endsection
I can launch the redis server without any problems.
I can launch the node socket.js server and I'm getting the response "Server running"
When I hit the route to the event I get the return "event fired" in my browser.
When I hit the route to the actual view
Route::get('test/view',function()
{
return view('testview');
});
I can see the whole page (layout is rendered), and the webconsole does not show any errors.
However if I fire the event, the view won't change, which means, the broadcast is not received right?
Now I included an output for the console
console.log(socket.connected);
which should show me if the client is connected to the socket.io right?
Well, the output says false. What am I doing wrong here?
Further information on my setup: I'm running the whole project on the php built-in server, the whole thing is running on Windows (if ever that could matter), my firewall is not blocking any of the ports.
EDIT 1:
I forgot to say that my node server is not receiving the messages as well... It only says "Server running", nothing else.
EDIT 2:
I used another socket.js:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
redis.subscribe('test-channel', function () {
console.log('Redis: test-channel subscribed');
});
redis.on('message', function(channel, message) {
console.log('Redis: Message on ' + channel + ' received!');
console.log(message);
message = JSON.parse(message);
io.emit(channel, message.payload)
});
io.on('connection', function(socket) {
console.log('a user connected');
socket.on('disconnect', function() {
console.log('user disconnected');
});
});
http.listen(3000, function() {
console.log('listening on *:3000');
});
And this time the console receives the messages.
So if the node socket.io receives the messages, then what's wrong with my client? Obviously the messages are being broadcasted correctly, the only thing is that they are not being received by the client...
I can't say what is exactly wrong and probably no one can't, because your problem is to broad and enviroment dependent. Using Wireshark Sniffer you can easily determinate part of solution that is not working correctly and then try find solution around actual problem.
If your question is about how to do that, I will suggest not involving node on server side and use .NET or Java language.
The problem with your code is you are connecting your client socket to the redis default port 6379 rather than the node port that is 3000.
So in your blade view change var socket = io('http://localhost:6379'); to var socket = io('http://localhost:3000');
have you tried to listen to the laravel queue, from command line, before to fire the event?
php artisan queue:listen
I'm new to node.js and socket.io and tried to connect the server to the client with the example from http://socket.io/#how-to-use. (no localhost)
Server:
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html'+err);
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.on('message', function(msg){
console.log('Got text: '+msg);
socket.broadcast.send(msg);
});
socket.on('disconnect', function () { });
});
Client:
<html><head><script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect();
socket.on('connect', function () {
alert('connected.');
socket.on('message', function (msg) {
// my msg
alert('message received: '+msg);
});
socket.send('hi');
});
</script>
</head><body>This is the content :)</body>
</html>
Google Chrome displays in the console:
Unexpected response code: 502
Also, after receiving every message, Chrome adds
GET http://[myServer]/socket.io/1/?t=1352313105809 socket.io.js:1659
Socket.handshake socket.io.js:1659
Socket.connect socket.io.js:1699
maybeReconnect
to the console.
Wheres the problem?
The examples from the How-To page all use port 80, which is common for serving websites.
However, you use port 8080 in your example.
Check your web browser's console if it even loads the socket.io script.
You may need to provide http://localhost:8080/socket.io/socket.io.js as explicit url and connect with io.connect('http://localhost:8080');
If the above does not work, please share some insight on what port your web server runs on.
There is no code to actually handle any incoming messages server-side in your (updated) example.
`socket.on('message', function(msg){
console.log('Got text: '+msg);
socket.send(msg);
});
should at the very least send the message back to the client - your alert is only triggered when the client receives a message. Does the node.js console output any incoming or sent messages? A few lines of my node.js console look like the following upon connecting.
debug - client authorized
info - handshake authorized ...
debug - setting request GET /socket.io/1/...
debug - set heartbeat interval for client ...
debug - client authorized for
debug - websocket writing 1::
debug - sending data ack packet
I've got a node.js server up and running with express and i'm trying to establish a websocket connection using socket.io server-side and chrome 12 client-side. When I try to connect, socket.io outputs a debug message saying "destroying non-socket.io upgrade" and the code in my connection handler doesn't run. Also on the client-side the readyState of my socket is 2 (CLOSING).
[edit]
readyState of the socket changed from 0 to 2
Make sure you're inserting the socket.io.js file into your client code and using it. If you try to create your own websocket on the client-side, you'll probably run into problems.
Do something like this for your server:
var app = require('express').createServer()
, io = require('socket.io').listen(app);
app.listen(80);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
and something like this for the HTML file you're serving:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
Make sure you're serving /socket.io/socket.io.js from your webserver dir. Then all you have to do is watch your console log in the web browser's Developer environment from the Options or with Firebug when you go to the page.