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

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}`);
});

Related

socket.io WebSocket connection failed

I am using socket.io to connect to a different domain, and it can successfully connect using polling, however when attempting to connect using websockets gets the error "WebSocket connection to 'wss://XXXXX' failed".
After observing the network activity the server seems to indicate that it is capable of upgrading to a websocket connection (although I won't claim to be an expert in understanding these requests), but isn't able to do so:
I'm just trying to produce a minimal viable product right now so here is my node.js server code:
let http = require('http');
let https = require('https');
let fs = require('fs');
let express = require('express');
const privateKey = fs.readFileSync('XXXXXXXXX', 'utf8');
const certificate = fs.readFileSync('XXXXXXXXX', 'utf8');
const ca = fs.readFileSync('XXXXXXXXX', 'utf8');
const options = {
key: privateKey,
cert: certificate,
ca: ca
};
let app = express();
let httpsServer = https.createServer(options,app);
let io = require('socket.io')(httpsServer, {
cors: {
origin: true
}
});
httpsServer.listen(443);
console.log('starting');
io.sockets.on('connection', (socket) => {
console.log("something is happening right now")
socket.on("salutations", data => {
console.log(`you are now connected via ${socket.conn.transport.name}`);
socket.emit("greetings", "I am the socket confirming that we are now connected");
});
});
Client-side JavaScript:
const socket = io("https://XXXXXXX");
console.log(socket);
socket.on("connect", () => {
console.log("now connected");
socket.on("message", data => {
console.log(data);
});
socket.on("greetings", (elem) => {
console.log(elem);
});
});
let h1 = document.querySelector('h1');
h1.addEventListener('click',()=>{
console.log("I am now doing something");
socket.emit("salutations", "Hello!");
})
The only suggestion in the official documentation for this issue isn't relevant because I'm not using a proxy, and other suggested fixes result in no connection at all (presumably because they prevent it from falling back to polling)
EDIT: also if it helps narrow down the problem, when querying my server using https://www.piesocket.com/websocket-tester it results in "Connection failed, see your browser's developer console for reason and error code"

Can't emit from server to client and from client to server [Socket.io]

I'm creating my product and stuck with this problem. One day I setuped socket.io and everything worked well. On the next day I migrate my server and client from http to https. After the migration client side and server side still connected, but I can't emit from client side to server and from server to client.
Server side
I have my ssl certificate inside ./security/cert.key and ./security/cert.pem they are loading correctly. My server running on https://localhost:5000
import fs from "fs";
import https from "https";
import socketio from "socket.io";
import express from "express";
// HTTPS optiosn
const httpsOptions = {
key: fs.readFileSync("./security/cert.key"),
cert: fs.readFileSync("./security/cert.pem"),
};
// Setup express and https server
const app = express();
const server = https.createServer(httpsOptions, app);
// Setup socket io
const io = socketio.listen(server, {
origins: "https://localhost:3000",
transports: ["websocket"],
});
server.listen(5000, () => {
console.log(`server listening on https://localhost:5000`);
});
io.listen(server);
io.on("connection", (socket) => {
console.log("new socket connected!");
console.log(`data = ${socket.handshake.query.data}`);
socket.emit("some-event");
socket.on("some-event-2", () => console.log("some-event-2 happened!"));
});
Client Side
My example react component. My react app is running on https://localhost:3000. HTTPS is connected and working well.
import React from "react";
import io from "socket.io-client";
const Sandbox: React.FC = () => {
const query = {
"data": 123,
};
const socket = io.connect("https://localhost:5000", {
secure: true,
query,
transports: ["websocket"],
});
socket.on("connect", () => console.log("connect!"));
socket.on("some-event", () => console.log("some event happened"));
socket.emit("some-event-2");
return <React.Fragment />;
};
export default Sandbox;
And now the problem. On client side in console I should see connect! and some event happened
And on server side I should see the messages new socket connected! and data = 123, some-event-2 happened!. But instead my client side console is completely clear
And server side console have only a few logs, but dont contains emit logs
What should I do? Maybe I'm incorrectly using socket.io with https?
I fixed my error.
The problem was that I was firstly create https server and after that only call .listen() on it. listen() - is not a void, it's return another server obj. You need to pass the result of .listen() function inside your io.listen()
// Don't do that❌
var server = https.createServer(options, app);
server.listen(5000);
io.listen(server);
// Do that✅
var server = https.createServer(options, app).listen(5000);
io.listen(server);

Sending data received from one socket.io server to a web socket client

I'm starting to use socket.io and I have a problem that I can't solve so far
I have two nodejs running, one is the socket.io data server and the other one is going to interact with web clients
I need to get data from the server and send it to my web clients, the problem is I can't emit data to the clients outside the 'on connect'
I think is better to explain it with a simple example
const socket = require('socket.io-client')('http://localhost:12000');
const SocketIO = require('socket.io');
const app = require('../app');
const server = http.createServer(app);
server.listen(port);
// client socket, this is a regular message from
// the server running on port 12000, it works
socket.on('msg_from_server', data => {
console.log(data);
});
// server socket
const io = SocketIO(server);
io.on('connection', (s) => {
// this works
s.emit('msg_to_client', {data: 'xxxx'})
// this doesn't works
socket.on('msg_from_server', data => {
console.log(data);
});
});
socket client for server on port 12000 and socket from io.on('connection', (socket) both are different. But you are mixing them both.Do something like this:
const Socket_12000 = require('socket.io-client')('http://localhost:12000');
const SocketIO = require('socket.io');
const app = require('../app');
const server = http.createServer(app);
server.listen(port);
// client socket
socket.on('msg_from_server', data => {
console.log(data);
});
// server socket
const io = SocketIO(server);
io.on('connection', (socket) => {
// this works
socket.emit('msg_to_client', {data: 'xxxx'})
// this doesn't works
Socket_12000.on('msg_from_server', data => {
console.log(data);
});
});
I have created a basic gist depicting the problem/solution please commant if you are looking something else.
https://gist.github.com/sandeepp2016/bb1946bcbeb2f11d57bc3aa2e44c158e

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