WebSocket connection established, but can't receive messages - javascript

I've written a short WebSocket example server in PHP yesterday. When the client connects to the server, the server reads the client Handshake and sends the server Handshake back with the appropriate key. onopen() of the client gets fired and the server and client seem to be connected.
My problem is: The server can't receive client messages and the client can't receive server messages. onmessage() wasn't triggered once and socket_select() never gives back the client that sent the message on server side.
function connect() {
try {
var webSocketURL = "ws://" + serverAddress + ":" + serverPort;
socket = new WebSocket(webSocketURL);
socket.onopen = function() {
log("Connected! (" + this.readyState + ")");
}
socket.onclose = function() {
log("Closed! (" + this.readyState + ")");
socket.close();
}
socket.onerror = function(error) {
log("Error: " + error.data);
socket.close();
}
socket.onmessage = function(message) {
log("Message from server: " + message.data);
}
}
catch (e) {
alert("Error: " + e);
}
}
The server code is a bit longer, but you can find it here.
Can anyone tell me what's wrong there? Is the handshake incorrect?
Client output:
Connected! (1)
Message to server: 0USERchannel
Server output.
Help is much appreciated, thank you.

On client side, enshure your socket variable is global.

Related

Javascript Websocket fails to receive TCP data

I'm trying to receive json data from an ESP32 via TCP to a website hosted thru WAMP (localhost -> ESP32 IP address on local network is 10.11.125:23). Below is my javascript function. My browser (Firefox Developer) generates a "SecurityError: The operation is insecure" when executing the line var connection = new webSocket('ws://10.11.13.125:23'). What am I missing??
function openWebsocket() {
console.log("open Websocket.....");
var connection = new WebSocket('ws://10.11.13.125:23');
connection.onerror = function(error) {
$("#Connection").html("Connection Error");
console.log("Websocket Error: " + error);
}
connection.onopen = function(evt) {
$("#Connection").html("Connected");
}
connection.binaryType = 'arraybuffer';
connection.onmessage = function(evt) {
console.log("Server: " + evt.data.byteLength);
}
console.log("ReadyState: "+connection.readyState);
}
I found the problem. The Chromium browser yields a more descriptive error message. Port 23 is not available. Switched over to
var connection = new WebSocket('ws://10.11.13.125:80');
and voila, everything works as expected.
Sorry for posting about an issue that in the end I found the solution for myself.

Node.js Processes Don't Detect Port is Already Being Used

I am trying to have two different Node processes (using Cluster) try to become servers to a Port. However, whenever the second process gets to the port, it doesn't detect that the port is being used.
I suspect the reason why they are not detecting if the port is open or not is due to the nature of callbacks (I'm detecting if the port is used or not using the portInUse function, so it is fetched asynchronously, and might cause some type of conflict later on).
Here is the code:
var cluster = require('cluster');
var net = require('net');
var PORT = 1337;
var list = {};
var portIsBeingUsed = false;
// Variable that detects if the port is in use.
var portInUse = function(port, callback) {
var server = net.createServer(function(socket) {
socket.write('Echo server\r\n');
socket.pipe(socket);
});
server.listen(port, 'localhost');
server.on('error', function (e) {
callback(true);
});
server.on('listening', function (e) {
server.close();
callback(false);
});
};
if (cluster.isMaster) {
for (var i = 0; i < 2; i++) {
cluster.fork();
}
Object.keys(cluster.workers).forEach(function(id) {
console.log("I am running with ID : "+ cluster.workers[id].process.pid);
list[cluster.workers[id].process.pid] = 0;
});
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else { // Rest of the logic with all Processes goes here.
// Get the Process ID of the current process in execution.
var pid = cluster.worker.process.pid;
console.log("This is process " + pid + " working now.\n");
// Verify if Port is being used.
portInUse(PORT, function(returnValue) {
if(returnValue) { // Become a Client to the Server
console.log("port " + PORT + " is being used.\n\n");
becomeClient(pid);
} else { // Become a Server
console.log("port" + PORT + " is not being used.\n\n");
becomeServer(pid);
}
});
}
function becomeServer(pid) {
var server = list[pid];
server = net.createServer(function (socket) {
socket.write('Hello Server 1\r\n');
socket.end("hello");
console.log("Someone connected to Server 1. \n");
socket.pipe(socket);
});
server.listen(PORT, function(){
console.log("Process " + pid + " has become the Server on Port " + PORT);
});
server.on("error", function() {
console.log("there was an error on Process " + pid);
console.log("this error was becoming a Server.");
});
}
function becomeClient(pid) {
var client = list[pid];
client = net.connect({port: PORT}, function() {
list[pid].write("I am connected to the port and my pid is " + pid);
});
client.on('data', function(data) {
console.log(data.toString());
list[pid].end();
});
client.on('end', function() {
console.log('disconnected from server');
});
}
And here is the output:
So the first process (In this case Process 9120) becomes the server on port 1337, but then the second process doesn't detect that the port is being used and somehow becomes the server as well (I would expect an EADDRINUSE here, not sure why it isn't showing any errors).
Any help or clarification as to why this isn't working would be greatly appreciated.
Thanks,
This is expected behavior and it is how the cluster module works (by default). It's what allows incoming requests to the same port to be easily distributed among the available workers.
A large part of the point of cluster involves port sharing, so that you can have multiple workers take turns serving requests. The worker processes just request a port from the master, which actually opens the port, and then the master hands requests back to any workers that have requested that port.

Node.js websocket-server and tcp-server connection

Related to this question Browser with JavaScript TCP Client I asked whether I can connect from a browser to a tcp server. I found out that it won't work so I asked for another solution. '0101' provided me to built up two servers. One tcp server for a c++ application that connects to and one websockets server that receives data from the browser. I have originally built up each one of them, but I don't know how to connect them so I can receive data from the browser in the c++ application.
Here is the websockets-server:
var ClientListe = {};
// Anzahl der Verbundenen Clients
var ClientAnzahl=0;
// Websocket-Server
var WebSocketServer = require('ws').Server
var wss = new WebSocketServer({host: '127.0.0.1',port: 80});
wss.on('connection', function(ws)
{
// Client-Anzahl hochzählen
ClientAnzahl++;
// Client-Verbindung mit in die Client-Liste Aufnehmen
ws['AUTH'] = ClientAnzahl;
ClientListe[ws['AUTH']] = ws;
// Ausgabe
console.log('client '+ClientAnzahl+' verbunden...');
ws.on('message', function(message)
{
console.log('von Client empfangen: ' + message);
for(client in ClientListe)
{
ClientListe[client].send('von Server empfangen: ' + message);
}
});
ws.on('close', function()
{
// Client aus der ClientListe Löschen
delete ClientListe[ws['AUTH']];
// Nachricht der Trennung an die Console ausgeben
console.log('Client '+ ws['AUTH'] +' getrennt.');
});
});
and here is the tcp server:
// Load the TCP Library
net = require('net');
// Keep track of the chat clients
var clients = [];
// Start a TCP Server
net.createServer(function (socket) {
// Identify this client
socket.name = socket.remoteAddress + ":" + socket.remotePort;
// Put this new client in the list
clients.push(socket);
// Send a nice welcome message and announce
socket.write("Welcome " + socket.name + "\n");
broadcast(socket.name + " joined the server\n", socket);
// Handle incoming messages from clients.
socket.on('data', function (data) {
broadcast(socket.name + " message: " + data, socket);
});
// Remove the client from the list when it leaves
socket.on('end', function () {
clients.splice(clients.indexOf(socket), 1);
broadcast(socket.name + " left the server.\n");
});
// Send a message to all clients
function broadcast(message, sender) {
clients.forEach(function (client) {
// Don't want to send it to sender
if (client === sender) return;
client.write(message);
});
// Log it to the server output too
process.stdout.write(message)
}
}).listen(80);
// Put a friendly message on the terminal of the server.
console.log("TCP Server running at localhost port 80\n");
Both are copied out of the internet for testing some cases
Create a TCP server (NodeJS example)
var net = require("net");
var server = net.createServer(function(c) { //'connection' listener
console.log('server connected');
c.on('end', function() {
console.log('server disconnected');
});
c.write('hello\r\n');
c.pipe(c);
});
server.listen(8124, function() { //'listening' listener
console.log('server bound');
});
Then in the same file (optionally of course) create a WS server with different port number
var WebSocketServer = require("ws").Server;
var wss = new WebSocketServer({
port: 8080
});
wss.on("connection", function(ws) {
console.log("CONNECTED");
// ws.on("message"), ws.on("close"), ws.on("error")
});
Now you should have two servers, one for regular sockets and another one for WebSockets.
// As I mentioned in the previous question and Pete as well, it is a lot better to use WebSockets in C++ as well instead of creating two servers...
Drop the TCP server and make the C++ client connect to the websockets server instead. You'll need to implement the websockets protocol on top of your TCP connection at the C++ end (all you really need is a bit of pre-amble to negotiate the websocket). You have problems here with both servers trying to use port 80.
By the way, you should also consider using HTTPS for the websocket instead of HTTP since it avoids problems with proxy traversal. But get the HTTP case working first as this will be more complicated to implement on the C++ end.

How do I build a simple node js server that sends and receives to a client?

I have a node js server, and a html/javascript client.
I simply want to allow the client to send a json-string to the node.js server, the server process's that string and returns a result string back to the client.
I started by setting up the html-client to call like so :
var msg =
{
type: "message",
text: "Hello"
};
function CallWebSocket()
{
var socket = new WebSocket("ws://127.0.0.1:8080","test");
socket.onopen = function (event)
{
alert(JSON.stringify(msg));
socket.send(JSON.stringify(msg));
};
socket.onmessage = function(event)
{
alert(event.data);
}
}
and node.js :
var net = require('net');
var server = net.createServer(function(socket)
{
// do what you need
socket.setEncoding("utf8");
socket.on('data', function(data)
{
var jsonData = JSON.parse(data);
socket.write(jsonData.text);
socket.end();
process.exit(0);
});
});
server.listen(8080);
but on the server I get this error :
undefined:1
``GET / HTTP/1.1
^
SyntaxError: Unexpected token G
at Object.parse (native)
at Socket.<anonymous> (/home/jay/projects/nodejs/test/json-server.js:8:23)
at Socket.EventEmitter.emit (events.js:95:17)
at Socket.<anonymous> (_stream_readable.js:746:14)
at Socket.EventEmitter.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:408:10)
at emitReadable (_stream_readable.js:404:5)
at readableAddChunk (_stream_readable.js:165:9)
at Socket.Readable.push (_stream_readable.js:127:10)
at TCP.onread (net.js:526:21)
Any help is much appreciated.
UPDATE
The updated server code :
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
response.end();
});
server.listen(8080, function() {
console.log((new Date()) + ' Server is listening on port 8080');
});
wsServer = new WebSocketServer({
httpServer: server,
// You should not use autoAcceptConnections for production
// applications, as it defeats all standard cross-origin protection
// facilities built into the protocol and the browser. You should
// *always* verify the connection's origin and decide whether or not
// to accept it.
autoAcceptConnections: false
});
function originIsAllowed(origin) {
// put logic here to detect whether the specified origin is allowed.
return true;
}
wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
// Make sure we only accept requests from an allowed origin
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
var connection = request.accept('echo-protocol', request.origin);
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log('Received Message: ' + message.utf8Data);
connection.sendUTF(message.utf8Data);
}
else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
This solved my problem and I am now getting the message back.
A websocket is not a plain TCP socket. That is basically the core of your problem.
The websocket protocol looks like a modified HTTP protocol that allows two way communication using a single (TCP) socket. Read the RFC for more info on how the websocket protocol actually works: https://www.rfc-editor.org/rfc/rfc6455#section-1.2
You have two options if you want to use websockets with node servers:
Read the RFC and write a function to handle the websocket protocol so you can pass that function to socket.on.
Use a websocket server module that someone else have written. Go to npm and search for "websocket server" or google "websocket server npm". There are lots of modules out there. Pick one you like best.
There is a third alternative. Use socket.io. Socket.io is a library that communicates between client and server using websocket if possible (preferred) but is able to degrade to other transports such as Flash and ajax on older browsers.

WebSockets Handshake not working

Im trying to get a connection between a JavaScript WebSocket and a TCP Server/Client applicat written in VisualBasic .Net . My problem is that the handshake fails. I do get a handshake request from the local website, but it does not accept my response.
The code of the JavaScript file:
<script type="text/javascript">
var ws;
function connect() {
if("WebSocket" in window) {
debugger;
ws = new WebSocket("ws://192.168.193.178:1925");
ws.onopen = function() {
alert("Connection established");
};
ws.onmessage = function(evt) {
var received_msg = evt.data;
alert("Message is received: " + received_msg);
};
ws.onerror = function(evt) {
alert("Error");
var received_msg = evt.data;
alert("Error: " + received_msg);
};
ws.onclose = function() {
// websocket is closed.
alert("Connection closed");
};
//ws.send("Test");
//ws.close();
} else {
alert("WebSocket NOT supported by your Browser!");
}
}
function disconnect() {
ws.close();
}
function send(message) {
ws.send(message);
alert("Sent: " + message);
}
</script>
The VB.Net code output:
Received:
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 192.168.193.178:1925
Origin: http://127.0.0.1:8020
Sec-WebSocket-Key: eGzO0afUD5jCeUdzdoxwjw==
Sec-WebSocket-Version: 13
Sent:
HTTP/1.1 101 Web Socket Protocol Handshake\r\n
Upgrade: WebSocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Origin: null\r\n
Sec-WebSocket-Accept: NzU3M2IwYzk0ZWFmYjg4MzMyZWI1ODhhZWI4NWUyZDE1YWU2YzhlNA==\r\n
\r\n
I just cant get the WebSocket to accept the handshake, I hope anyone can help me out.
Maybe the hash-generation contains errors?
Edit:
I now get the correct Sec-WebSocket-Accept String (dXOwyU6vuIMy61iK64Xi0VrmyOQ=), anyway the WebSocket seems not to handle the handshake response. I tried debugging it with the Chrome Developer Tools, but I don't get usefull information from it. Any tips?
One thing sticks out immediately. The Sec-WebSocket-Accept value in the server response is much longer than what a correct value looks like. In fact, the correct value for that Key should be "dXOwyU6vuIMy61iK64Xi0VrmyOQ=". My guess is you're doing the base-64 encoding on the string representation of the SHA1 result. The encoding should be done on the byte representation of SHA1 result.

Categories

Resources