I am trying to set up a simple websocket server that communicates between a Flash AS3 client and a Node.js backend. The following code is when both the client and server are hosted locally. The code also functions properly when the swf is hosted locally connected to the server hosted on heroku. The socket only fails when both the swf and the server are hosted online.
Node.js Code (Server)
var WebSocketServer = require("ws").Server
var net = require('net');
var http = require("http")
var express = require("express")
var app = express()
var crossdomain = require('crossdomain')
var port = process.env.PORT || 5000;
app.use(express.static(__dirname + "/"))
var xml = crossdomain({ domain: '*' });
app.all('/crossdomain.xml', function (req, res, next) {
res.writeHead(200, { 'Content-Type': 'application/xml; charset=utf-8' });
res.write(xml);
//res.write(new Buffer([0x00]))
res.end();
});
var server1 = http.createServer(app)
server1.listen(port)
console.log("http server listening on " + port)
var wss = new WebSocketServer({server: server1})
wss.on("connection", function(ws) {
console.log("Connected");
ws.on("close", function() {
console.log("websocket connection close")
})
})
Crossdomain file - example.com/crossdomain.xml
<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="*"/>
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*" secure="false"/>
</cross-domain-policy>
AS3 Code (Client) - I'm Using (https://github.com/theturtle32/AS3WebSocket)
import com.worlize.websocket.*;
Security.loadPolicyFile("http://example.com/crossdomain.xml");
var websocket:WebSocket = new WebSocket("ws://example.com", "*", "echo-protocol");
websocket.addEventListener(WebSocketEvent.OPEN, handleWebSocketOpen);
websocket.connect();
var con = false;
function handleWebSocketOpen(event:WebSocketEvent):void {
trace(event);
}
When the client is accessed from the server a request for the crossdomain.xml does occur and it gets returned successfully to the client, but at that point nothing happens anymore. I've been trying to solve this for ages with no luck. I did find that when you return the crossdomain file you need to end it with a 0x00 for it to be properly read, but I haven't found a way to make to that work. I've tried adding res.write(new Buffer([0x00])) to the response from the crossdomain request as well as several other modifications to no avail. These all seem to stop the xml file from being valid anyway.
I would greatly appreciate if anyone could help in getting this to work, I've been struggling with it for an extremely long time and can't quite seem to get this last step working.
Related
I am trying to make a simple server with socket.io and express and connect to it through a website.
when i followed a tutorial on socketio with localhost, everything worked fine, but when i put the server on a vserver, and tried to connect to it, i got this error:
Failed to load resource: net::ERR_SSL_PROTOCOL_ERROR
as well as:
GET https://54.53.0.254:47185/socket.io/?EIO=4&transport=polling&t=O09jjrs net::ERR_SSL_PROTOCOL_ERROR
here is my server code:
const express = require('express');
const app = express();
const server = app.listen(47185);
const socket = require('socket.io');
const io = socket(server)
console.log('server running on port 47185');
io.sockets.on('connection', newConnection);
function newConnection(socket) {
console.log('new connection: ' + socket.id);
socket.on('input', inputLog)
function inputLog(data) {
socket.broadcast.emit('input', data);
console.log(data);
}
}
and here is my client code (this is all that relates to socket.io, the rest is just for the website)
var options = {
rejectUnauthorized:false
}
var socket;
socket = io.connect('89.58.0.199:47185', options);
socket.on('input', foreignInput)
function foreignInput(data) {
terminal_animate('\n' + data)
}
i have tried many different fixes and googled everything i can think of, and i'm just not sure what the problem is.
can anyone help me out with this issue? thanks in advance.
In the documentation, according to the Client Initialization part, in node.js you should provide the protocol when connecting to the server.
// the following forms are similar
const socket = io("https://server-domain.com");
const socket = io("wss://server-domain.com");
const socket = io("server-domain.com"); // only in the browser when the page is served over https (will not work in Node.js)
The first two example shows the secure https/wss as protocol, for that you need to serve the required files from the server, example in the documentation.
With http/ws as protocol it should work, but the communication will not be secure.
The Server Initialization / With Express shows an example to call .listen on the return value of createServer from the http module, with the app given as a parameter.
const express = require("express");
const { createServer } = require("http");
const { Server } = require("socket.io");
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, { /* options */ });
io.on("connection", (socket) => {
// ...
});
httpServer.listen(3000);
With a caution that says:
Using app.listen(3000) will not work here, as it creates a new HTTP server.
I’ve developed myself a little WebSocket Server which works perfectly (local - on my IDE). The problem is that I want to host it on my server managed with Plesk under a specific subdomain that I've created: ws.my-url.de.
This is my server.js file:
const {logInfo} = require('./logger');
const WebSocketServer = require('ws').Server;
const express = require('express');
const uuid = require('node-uuid');
const app = express();
const wss = new WebSocketServer({
server: app.listen(process.env.PORT || 8888)
});
logInfo('WebSocket Server successfully started');
wss.on('connection', ws => {
ws.id = uuid.v4();
logInfo(`Client connected: ${ws.id}`);
ws.on('message', function () {
logInfo(`New message from client: ${ws.id}`);
});
ws.on('close', function () {
logInfo(`Client: ${ws.id} closed connection`);
});
});
wss.on('close', function () {
logInfo('WebSocket Server stopped');
});
app.post('/', function (req, res) {
logInfo(req);
});
I've also implemented a logger that logs out to a file which works also great (directly on start e.g. my startup message) but inside the logs folder on my server is a yawning emptiness.
I really can't get my WebSocket Server running on my server. To leave no stone unturned, I've disabled the proxy mode from nginx but after trying to connect to wss://ws.my-url.de I'm getting this error:
WebSocket connection to 'wss://ws.my-url.de/' failed: Error during WebSocket handshake: Unexpected response code: 500
So I can say that my server is not starting. To be really sure (and to exclude other things), I've wrote a little http server found in the internet and this ran straight out of the box after pressing the Restart App button (I saw the response in the browser window):
const http = require('http');
http.createServer(function(request, response) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('App is running…');
}).listen(process.env.PORT);
This is my configuration by the way:
When I open the URL after trying to start my WebSocket Server, I'm getting this error:
So what I'm doing wrong here? I don't want a page I can open, I just want to get this running as a little service which is accessible over my subdomain. I'm very overwhelmed with this and thankful for every person who can help me.
Another update:
The problem occurs when running on localhost as well. Since I figured out the problem comes from the proxy server, here's its code :
var serverBouncer = bouncy(function(req, res, bounce) {
var path = req.url;
var url = req.headers.host;
if (typeof url !== "string")
return;
var urlArray = url.split('.');
var bouncePort = port;
if (!isNaN(urlArray[0]))
bouncePort = parseInt(urlArray[0]);
else if (String(urlArray[0]).toLowerCase() === "www" && !isNaN(urlArray[1]))
bouncePort = parseInt(urlArray[1]);
bounce(bouncePort);
});
serverBouncer.listen(80);
Update:
I found where the problem came from!!! But I still need to find the solution... There seems to be issues with using newer versions of Socket.io (>= 1.0) with a proxy server (bouncy, in my case).
I recently updated Socket.IO from v0.9.16 to v1.4.5, as well as adding Express to the mix. However, now I cannot open multiple (number seems to vary) tabs in Chrome and Firefox without experiencing strange issues (Edge is the only one to work well). It either hangs, or partially loads html and other resources before it hangs.
After waiting, I often get the error :
Failed to load resource: the server responded with a status of 400 (Bad Request)
When I close one of the tab that's been hanging, it unblocks the other tabs that were also hanging.
The issues were not present before going through with the changes listed above.
I've been doing research for 2 full days and just now decided to post this, as I know it's very vague and I'm probably not providing enough information. As much as I'd like to, it would take a very long time to remember and list everything I tried during that time.
Using Windows 10 with Chrome v51.0.2704.103, Firefox v43.0.1. The server (CentOS) is using node v6.2.2 with mainly the following modules :
express#4.14.0
npm#3.9.5
socket.io#1.4.5
Here's some relevant server code :
var port = 8502;
var socketio = require('socket.io');
var express = require("express");
var http = require('http');
var app = express();
var server = http.createServer(app);
var io = socketio.listen(server);
server.listen(port);
app.get('/', function(req, res, next) {
//Returning index.html
});
io.on("connection", function(socket) {
//Some events...
});
Here's a bit of the client code :
var client = io.connect();
client.on('connect', function() {
//Some events
})
your binding before the server is listening, try something like this
var app = express();
server = app.listen(PORT, function () {
console.log('Example app listening on port ' + PORT + '!');
});
io.listen(server);
I managed to replace the bouncy module with nginx. See my other question for the solution.
nginx : redirect to port according to domain prefix (dynamically)
I've got a Vagrant box set up to port-forwards a socket.io application from internal port 5000 to external port 8081; when I try to connect from the client it starts long-polling the connection but I don't see any kind of response from the server and the server app never registers a connection attempt. The connection doesn't fail or return any error response code though, it just returns a 200 code with a blank response.
// Import utilities
var http = require('http'),
socketIO = require('socket.io'),
querystring = require('querystring');
// Init servers/external connections
var server = http.createServer(function baseHandler(req, res) {
// console.log(req.headers);
res.writeHead(200);
res.end(JSON.stringify({
message: 'This server only supports WebSocket connections'
}));
}),
io = socketIO(server);
server.listen(process.env.socket_port || 5000, function() {
var sockets = [];
console.log('App connected');
});
io.on('connection', function (socket) {
console.log('Socket connected');
console.log('Socket in rooms '+ socket.rooms.join(', '));
});
The same app works just fine when I'm trying to connect from the app running directly on my PC, so my code doesn't seem to be the problem here, especially given how it's basically duplicating the basic example in the docs; not really sure how to solve this from here.
This is one of those really stupid bugs which crop up when you're working on two different problems with the same codebase at the same time. Here's the client-side code line which was breaking:
var socket = io('127.0.0.1:8081/?access_token=1d845e53c4b4bd2e235a66fe9c042d75ae8e3c6ae', {path: '/auth/socket.io'});
Note the path key is set to point to a subdirectory, /auth, which is a leftover from my work to get an nginx folder proxying to an internal port which the server was working on.
I'm unsuccessfully attempting to create an pub-sub instant messaging service. I am unable to receive messages in browser client.
The following code is from my client1.html file. I believe the trouble I'm having relates to the client unsuccessfully subscribing to '/channel'. I've added the alerts and am receiving the 'BEFORE & AFTER' but not the 'DURING' and the message.text is not appearing on the console. Any thoughts as to why a client cannot see the messages on the browser would be appreciated.
var client = new Faye.Client('/faye',{
timeout: 20
});
alert("BEFORE client subscription");
client.subscribe('/channel', function(message) {
$('#messages').append('<p>' + message.text + '</p>');
alert("DURING client subscription");
console.log(message.text);
});
alert("AFTER client subscription");
The browser console repeats the following error repeatedly:
POST http://my.server#server:8000/faye 404 (Not Found)
This error points to 'faye-browser.js:2023' which refers to the following line:
xhr.send(Faye.toJSON(message));
EDIT
This is is the server.js file
var fs = require("fs");
var config = JSON.parse(fs.readFileSync("config.json"));
var host = config.host;
var port=config.port;
var express = require("express");
var Faye = require('faye');
var bayeux = new Faye.NodeAdapter({mount: '/faye', timeout:45});
var app = express();
app.configure(function(){
app.use(express.bodyParser());
app.use(express.static('/'+__dirname));
});
app.post('/message', function(request, response){
bayeux.getClient().publish('/channel', {text:request.body.message});
console.log('broadcast message:' + request.body.message);
response.send(200);
});
bayeux.attach(app);
app.listen(port);
I've just configured Faye for our application, you are doing
bayeux.attach(app);
app.listen(port);
did not work for me, what worked is this
bayeux.attach(app.listen(port, function() {}));
I also think that you should use the whole url when you are creating Faye, not just the final part, like so:
var client = new Faye.Client('http://my.url.com/faye', { timeout: 20 });