socket.io connection event never fire - socket.io

server
var io = require('socket.io'),
UUID = require('node-uuid'),
gameport = 3000;
var db = {
waiting_clients: []
};
var logic = {
};
var sio = io.listen(gameport);
sio.sockets.on('connection', function(socket){
var client = {
id: UUID()
};
socket.emit('news', client);
console.log(client.id);
db.waiting_clients.push(client);
});
test client:
var net = require('net');
var client = net.connect({port: 3000},
function(e) { //'connect' listener
console.log('client connected');
client.end();
});
in test client console, it show "client connected". But there are no output in server console

You must use a socket.io client to connect to a socket.io server. Your code shows that you are trying to make a generic TCP connection to a socket.io server. That will not work. The lowest level connection will be established, but then the initial protocol handshake will fail and the socket.io server will drop the connection and you will never get the connection event.
Socket.io has its own connection scheme built on top of webSocket which is built on top of HTTP which is built on top of TCP.
So, to connect to a socket.io server, you must use a socket.io client that runs both the socket.io and webSocket protocol, not a plain TCP socket.

Related

Why is my Socket.IO server not responding to my Firecamp and C# clients?

I am trying to set up a very basic Socket.IO server and a .NET / Firecamp client to learn how to send events between the two.
My Javascript Socket.IO server is set up like this:
const
http = require("http"),
express = require("express"),
socketio = require("socket.io");
const app = express();
const server = http.createServer(app);
const io = socketio(server);
const SERVER_PORT = 3000;
io.on("connection", () => {
console.log("Connected");
io.emit("foo", "123abc");
});
server.listen(SERVER_PORT);
I am able to connect with a simple Socket.IO Javascript file:
const
io = require("socket.io-client"),
ioClient = io.connect("http://localhost:3000");
ioClient.on('connect', () => {
console.log("connected");
});
When I try to connect with Firecamp or this C# library I never see a connection event fired.
I looked at the default options for the Socket.IO JS client and tried to reproduce them in Firecamp: https://socket.io/docs/v3/client-api/index.html
The most important ones seem to be the Path= /socket.io, ForceNew = True, and Transports = polling, websocket. I decided to remove the polling transport because I kept getting an XHR polling error, but the websocket also times out in both C# and Firecamp.
I have tried connecting to "http://localhost:3000" and just "http://localhost".
Here is a screenshot of my Firecamp settings
I am also seeing a similar issue with my C# program
Quobject.Collections.Immutable.ImmutableList<string> trans = Quobject.Collections.Immutable.ImmutableList.Create<string>("websocket");
IO.Options options = new IO.Options();
options.Port = 3000;
options.Agent = false;
options.Upgrade = false;
options.Transports = trans;
client = IO.Socket("http://localhost:3000", options);
client.On(Socket.EVENT_CONNECT, () =>
Console.WriteLine("Connected"));
client.On(Socket.EVENT_CONNECT_ERROR, (Data) => Console.WriteLine("Connect Error: " + Data));
client.On(Socket.EVENT_CONNECT_TIMEOUT, (Data) => Console.WriteLine("Connect TImeout Error: " + Data));
client.On(Socket.EVENT_ERROR, (Data) => Console.WriteLine("Error: " + Data));
client.Connect();
If I only use a websocket transport I timeout in both Firecamp and C#. If I enable polling I receive the below error:
Error: Quobject.EngineIoClientDotNet.Client.EngineIOException: xhr poll error ---> System.AggregateException: One or more errors occurred. ---> System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at Quobject.EngineIoClientDotNet.Client.Transports.PollingXHR.XHRRequest.<Create>b__7_0()
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at Quobject.EngineIoClientDotNet.Client.Transports.PollingXHR.XHRRequest.Create()
--- End of inner exception stack trace ---
What other configuration settings can I toggle to try to get my Firecamp or C# connection to show up in my JS Server? I am receiving an "XHR Poll error" from the polling transport, and a timeout from the websocket transport. Is there additional debugging info somewhere I can use to determine where my problem lies? I think if I can get the communication working in either Firecamp or C# I should be able to get it working in the other environment.
I am assuming you're using the SocketIO v3 client. Firecamp is only supporting SocketIO v2. But the good news is in just two days Firecamp is going to give support for SocketIO v3 in the new canary release. I'll keep you posted here.
edited on 7th Sep'21
Firecamp is now supporting SocketIO v2, v3, and v4.
As mentioned above, Firecamp isn't optimized yet for the new version of Socket.IO (v4).
so meanwhile you can choose to manually enable compatibility for Socket.IO v2 clients.
All you have to do is to add "allowEIO3: true" (without quotes) as a key:value pair to the option object and pass this object when you create the server.
this will allow you to communicate with the server via Firecamp.
source https://socket.io/docs/v4/server-api/#Server
below you'll find an example for a working socket.io server integrated with express server.
const app = require('express')();
const httpServer = require('http').createServer(app);
const options = {
allowEIO3: true,
};
const io = require('socket.io')(httpServer, options);
app.get('/', (req, res) => {
res.send('home endpoint');
});
io.on('connection', (socket) => {
socket.on('new-connection', (data) => {
console.log(socket.id, 'connected');
socket.broadcast.emit('test-event', { name: data.name });
});
// when the user disconnects.. perform this
socket.on('disconnect', () => {
console.log(`${socket.id} disconnected`);
});
});
const port = 3000;
httpServer.listen(port, () => {
console.log(`server running on port ${port}`);
});

Connecting socket.io client to https

I'm trying to build a web chat application and want to connect my client to the socket.io server with https.
Seems like everything's fine, but the client is not connecting after all..
Server Code:
var app = require('express')();
var fs = require('fs');
var options = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
};
var server = require('https').createServer(options, app).listen(3000,function(){
console.log("Https server started on port 3000");
});
var io = require('socket.io').listen(server);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
console.log("Client connected");
/*....*/
});
Client code to connect to server:
$(function($){
var socket = io.connect('https://localhost:3000', {secure: true});
.....
});
It kind of doesn't run the code inside of $(function($)..
When I make it a http server it works just fine..
Simply
var socket = io.connect('/', {secure: true});
EDIT: By default socket.io will try to establish a connection on the same host as webserver hosts web content, so no need to specifying host/protocol/port. The / states to connect to default namespace.
I solved the problem..
So for http it was enough if you begin your script on the client with
$(function(){
....
});
But it wouldn't work with https.
I changed it to
jQuery(function($){
....
})(jQuery);
Pretty odd but it worked for me.

socket.io - passing events between nodes

I was inspired by this: http://socket.io/docs/using-multiple-nodes/#passing-events-between-nodes, and right now I want to synchronize my two socket.io instances through the redis adpter.
This is my code:
//FIRST SERVER (server1.js)
var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
var test = 0;
io.on('connection', function (socket) {
test+=1;
console.log("connection. test = " + test);
});
//SECOND SERVER (server2.js)
var io = require('socket.io')(4000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
var test = 0;
io.on('connection', function (socket) {
test+=1;
console.log("connection. test = " + test);
});
When I connecting to server1.js (port 3000) - I see 'connection. test = 1', it's good, but the console of the second server is still clean. I want second server (port 4000) to do the same (print 'connection = 1').
What I'm doing wrong? Can you show me an example how to use the adapter?
Thanks
If you only connect to server1:3000 there's no way the io.on('connection', ...) would be triggered on server2:4000 - after all, you are not connected to that server.
Each client will connect to only one of your servers. If you were not using the Redis adapter clients connected to different servers would be unable to communicate. Now with the Redis adapter the servers know about the clients of each other and can broadcast messages to all connected clients of all servers.

Is it possible to use socket.io server with pure html5 websockets?

I want to use sockets in my web app. I don't want to use socket.io library on client-side. It's OK for server-side though. Can I do this?
Now with socket.io on server and pure websocket on client I have destroying non-socket.io upgrade error. I've googled that it means that I have to use socket.io-client library on client-side. Is there any way to avoid that? I don't want client to be tight with this library and use pure html5 websocket instead.
If it's not possible what should I use for server to connect with pure html5 websockets?
If someone is curious here is my server code (coffeescript file)
# Require HTTP module (to start server) and Socket.IO
http = require 'http'
io = require 'socket.io'
# Start the server at port 8080
server = http.createServer (req, res) ->
# Send HTML headers and message
res.writeHead 200, { 'Content-Type': 'text/html' }
res.end "<h1>Hello from server!</h1>"
server.listen 8080
# Create a Socket.IO instance, passing it our server
socket = io.listen server
# Add a connect listener
socket.on 'connection', (client) ->
# Create periodical which ends a message to the client every 5 seconds
interval = setInterval ->
client.send "This is a message from the server! #{new Date().getTime()}"
, 5000
# Success! Now listen to messages to be received
client.on 'message', (event) ->
console.log 'Received message from client!', event
client.on 'disconnect', ->
clearInterval interval
console.log 'Server has disconnected'
And here is a client-side
<script>
// Create a socket instance
socket = new WebSocket('ws://myservername:8080');
// Open the socket
socket.onopen = function (event) {
console.log('Socket opened on client side', event);
// Listen for messages
socket.onmessage = function (event) {
console.log('Client received a message', event);
};
// Listen for socket closes
socket.onclose = function (event) {
console.log('Client notified socket has closed', event);
};
};
</script>
I've found this library, seems OK for my needs https://npmjs.org/package/ws

Socket.io connection url?

I have the current setup:
Nodejs Proxy (running http-reverse-proxy) running on port 80.
Rails server running on port 3000
Nodejs web server running on port 8888
So any request starting with /nodejs/ will be redirected to nodejs web server on 8888.
Anything else will be redirected to the rails server on port 3000.
Currently Socket.io requires a connection url for io.connect.
Note that /nodejs/socket.io/socket.io.js is valid and returns the required socket.io client js library.
However, I am not able to specify connection_url to /nodejs/ on my server.
I have tried http://myapp.com/nodejs and other variants but I am still getting a 404 error with the following url http://myapp/socket.io/1/?t=1331851089106
Is it possible to tell io.connect to prefix each connection url with /nodejs/ ?
As of Socket.io version 1, resource has been replaced by path. Use :
var socket = io('http://localhost', {path: '/nodejs/socket.io'});
See: http://blog.seafuj.com/migrating-to-socketio-1-0
you can specify resource like this:
var socket = io.connect('http://localhost', {resource: 'nodejs'});
by default resource = "socket.io"
If you are using express with nodejs:
Server side:
var io = require('socket.io')(server, {path: '/octagon/socket.io'});
then
io.on('connection', function(socket) {
console.log('a user connected, id ' + socket.id);
socket.on('disconnect', function() {
console.log('a user disconnected, id ' + socket.id);
})
})
socket.on('publish message ' + clientId, function(msg) {
console.log('got message')
})
Client side:
var socket = io('https://dev.octagon.com:8443', {path: '/octagon/socket.io'})
then
socket.emit('publish message ' + clientId, msg)
I use below approach to achieve this goal:
client side:
var socket = io.connect('http://localhost:8183/?clientId='+clientId,{"force new connection":true});
server side:
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(socket) {
console.log("url"+socket.handshake.url);
clientId=socket.handshake.query.clientId;
console.log("connected clientId:"+clientId);
});
reference:https://github.com/LearnBoost/socket.io/wiki/Authorizing#global-authorization
If you are serving your app with express, then maybe you can check this out. Remember express uses http to serve your application.
const express = require('express'),
http = require('http'),
socketIo = require('socket.io'),
app = express()
var server = http.createServer(app);
var io = socketIo(server);
io.on('connection', (socket)=>{
// run your code here
})
server.listen(process.env.PORT, ()=> {
console.log('chat-app inintated succesfully')
})

Resources