Simple example on how to use Websockets between Client and Server - javascript

I am new to websockets and just trying to get a handle of how to listen to a message from a client browser from the server and vice-versa.
I'm using a Node.js/Express setup and just want to be able to firstly listen for any messages from the client.
I've been looking at this https://github.com/websockets/ws library and have tried the examples but am not able to get this working within my localhost environment.
I'm also not clear what I need to look out for, when I'm listening for a message.
What code do I use on the client, i.e. url + port and what code do I use on the server?
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost/path', {
perMessageDeflate: false
});

Using websockets directly might be troublesome, it's advised you use a framework to abstract this layer, so they can easily fallback to other methods when not supported in the client. For example, this is a direct implementation using Express js and Websockets directly. This example also allows you to use the same server for HTTP calls.
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
//initialize a simple http server
const server = http.createServer(app);
//initialize the WebSocket server instance
const wss = new WebSocket.Server({ server });
wss.on('connection', (ws) => {
//connection is up, let's add a simple simple event
ws.on('message', (message) => {
//log the received message and send it back to the client
console.log('received: %s', message);
ws.send(`Hello, you sent -> ${message}`);
});
//send immediatly a feedback to the incoming connection
ws.send('Hi there, I am a WebSocket server');
});
//start our server
server.listen(3000, () => {
console.log(`Server started on port ${server.address().port} :)`);
});
For the client, you can do something like this:
const ws = new WebSocket('ws://localhost:3000')
ws.onopen = () => {
console.log('ws opened on browser')
ws.send('hello world')
}
ws.onmessage = (message) => {
console.log(`message received`, message.data)
}
Like i have mentioned above, it is advised that you use a mature framework for websockets. Should your app be minimal and not need scaling, you can use any open source library, with socket.io being the most popular.
However, if you are talking about implementing this to be used at production level, you should know that the open source solutions do not allow for scalability, failover, message ordering etc. In that case, you’ll have to implement a realtime platform as a service tool.

Just a note, socket.io is a backend/frontend library that uses websocket but also has a number of fallbacks if the client browser does not support websocket. The example below works with ws backend.
Server
const WS = require('ws')
const PORT = process.env.PORT || 8080
const wss = new WS.Server({
port: PORT
}, () => console.log(`ws server live on ${PORT}`))
const errHandle = (err) => {
if(err) throw err
}
wss.on('connection', (socket) => {
console.log('something connected')
socket.send('you are connected', errHandle)
socket.on('message', (data) => {
console.log(`socket sent ${data}`)
socket.send('message received', errHandle)
})
})
client (browser)
(() => {
const ws = new WebSocket('ws://localhost:8080')
ws.onopen = () => {
console.log('ws opened on browser')
ws.send('hello world')
}
ws.onmessage = (message) => {
console.log(`message received ${message}`)
}
})()
edit: oh, and ws and http are different protocols. you will need a different server to serve your http files

Related

Websocket client not connecting to server (nodejs)

I have a NodeJS express app which listens on port 3000. In that app I define a websocket connection like so:
const express = require('express');
const app = express();
const server = require("http").createServer(app);
const WebSocket = require("ws");
const wss = new WebSocket.Server({ server });
wss.on("connection", ws => {
ws.send("You (the client) connected");
ws.on("message", msg => {
ws.send("Server received your msg: " + msg);
});
});
app.listen(3000, () => {console.log("Listening on port 3000");});
This code is on the NodeJS backend, and it listens for websocket connections. It sends a message to the client when the client connects, and when the client sends a message.
On the font end, I have the following vanilla JavaScript code inside my index.html:
const socket = new WebSocket("ws://my.url.com:3000");
socket.addEventListener("open", evnt => {
console.log(evnt);
socket.send("Меssage from client");
});
socket.addEventListener("message", evnt => {
console.log("Received msg from server:", evnt.data);
});
But my code does not work: when I run the front-end code, the socket object (in the front end) never connects; when I try to call socket.send I get an error:
Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
Eventually the connection times out but the client socket never connects to the socket on the server. How can I fix my code so that the client side can connect successfully?
You can use socket.readyState to check what state the server is in.
There are four possible states: CONNECTING, OPEN, CLOSING, or CLOSED. So if you used a function like this:
window.setInterval(function() {
if(socket.readyState == 'OPEN') {
//send while open
}
}, 500)
Then that should do the trick. Read more about it here

Can't get Websockets / wss to work at all on simple app

I've been fiddling around with WebSockets the past few days and got some success. Particularly, I am able to have a client connect to a server over "ws://localhost:8080". However, the second I change this to "wss://localhost:8080", my client can no longer connect, and as the best the WebSocket API can tell me is "haha you got an error", and I have no idea how to fix this. I am using the Microsoft Edge browser to support the client, and node.js / express to set up the server. I have been scouring the web for answers to not much success. My only guess is that Edge is messing around with my WebSocket connections. Overall, my end goal with this is to fix another issue in one of my programs where "wss" connections worked for 2 weeks and then suddenly didn't. Any help or insight would be much appreciated.
Update: I got "wss" to work by exposing "localhost:8080" via ngrok. However, something even stranger happens -- half the time, the WebSocket connection is made and everything works fine. But the other half -- the websocket connection fails. I am really stuck.
Here is some relevant code:
Client:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name="viewport" content = "width-device-width, initial-scale-1.0">
<title>Socket Thing 1</title>
</head>
<body>
Client1
<button
onclick="sendMessage()">Send Msg</button>
</body>
<script>
const socket = new WebSocket('wss://localhost:8080');
socket.addEventListener('open', function (event) {
console.log('Connected to Web Socket server');
});
socket.addEventListener('message', function (event) {
console.log("Client 1 received new message from server");
});
socket.onerror = (event) => {
console.error("Web Socket error observed: " + event);
}
const sendMessage = () => {
socket.send('Hello from Client1');
}
</script>
</html>
Server:
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const WebSocket = require('ws');
const wss = new WebSocket.Server( { server });
wss.on('connection', ws => {
console.log('New client connected');
ws.send('Welcome new client');
ws.on('message', message => {
console.log('Received a message: ' + message);
ws.send("Message from server: Got your message");
wss.clients.forEach(function each(client) {
// don't send to current ws client
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message); // send to all other clients
}
});
});
});
app.get('/', (req, res) => res.send('Hello World!'));
server.listen(8080, () => console.log('Listening on port : 8080'));
It looks like your server can not satisfy a request comeing in via wss://.
Handling communication through ws:// is different to wss:// .
In order to do so you have, among other things, to let the server know where your cetificate and private key are located in order to start secure communication with your client.
You probably get an idea reading this implementing-https-and-wss-support-in-express

Javascript: Can I open websocket server connection at random port

I want to create webserver socket connection at random port. And I want to return server port to calling application or just print it in terminal.
The typical code to create a server connection is as below.
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 0 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
So I am trying to create server at port 0. I assume it will create server at random port. How do I get that random port?
I want to know the port number, as soon as server socket is created.
Now I am able to create the websocket server at random port and able to get the port number as well. Not sure if it is the right way, but it works.
const http = require('http');
const WebSocket = require('ws');
const url = require('url');
const server = http.createServer();
const wss = new WebSocket.Server({ noServer: true });
wss.on('connection', function connection(ws) {
console.log(wss);
});
server.on('upgrade', function upgrade(request, socket, head) {
const pathname = url.parse(request.url).pathname;
wss.handleUpgrade(request, socket, head, function done(ws) {
wss.emit('connection', ws, request);
});
});
server.listen(0, '127.0.0.1', function incoming() {console.log (server.address().port);});
Websocket works with http/s on port 80 or 443. The server may listen on any port it chooses, but if it chooses any port other than 80 or 443, it may have problems with firewalls and/or proxies. Browsers generally require a secure connection for WebSockets, although they may offer an exception for local devices.

Javascript Websocket server message broadcast to clients

I am trying to create a dummy websocket server in javascript to send some message to my android client app. The messages will be injected to the server using a html page( javascript ), which will further be passed on to the android client. I am able to connect these two clients (web and android) individually with the server, however, unable to achieve the flow I want, i.e. Web based javascript sends message to running Nodejs websocket server, which broadcast this message to the android client.
This is the code I am using for server side
var WebSocketServer = require("ws").Server;
var http = require("http");
var express = require("express");
var port = 2001;
var app = express();
app.use(express.static(__dirname + "/../"));
app.get('/someGetRequest', function(req, res, next) {
console.log('receiving get request');
});
app.post('/somePostRequest', function(req, res, next) {
console.log('receiving post request');
});
app.listen(80); //port 80 need to run as root
console.log("app listening on %d ", 80);
var server = http.createServer(app);
server.listen(port);
console.log("http server listening on %d", port);
var userId;
var wss = new WebSocketServer({
server: server
});
wss.on("connection", function(ws) {
console.info("websocket connection open");
var timestamp = new Date().getTime();
userId = timestamp;
ws.send(JSON.stringify({
msgType: "onOpenConnection",
msg: {
connectionId: timestamp
}
}));
ws.on("message", function(data, flags) {
console.log("websocket received a message");
var clientMsg = data;
ws.send(JSON.stringify({
msg: {
connectionId: userId
}
}));
console.log(clientMsg);
});
ws.on("close", function() {
console.log("websocket connection close");
});
});
console.log("websocket server created");
WebClient:
< script type = "text/javascript" >
var websocketURL = 'ws://localhost:2001/';
function startWebSocket() {
try {
ws = new WebSocket(websocketURL);
} catch (e) {
alert("Unable to connect to webserver")
}
}
function sendMessage(text) {
var message = 'Test message from webclient: ' + text;
ws.send(message);
alert(message);
}
startWebSocket(); < /script>
<button onclick="sendMessage('From button1')">Button 1</button > < br >
< button onclick = "sendMessage('From button2')" > Button 2 < /button><br>
Android client:
Just using socket class and its method to do further processing
s = new Socket(HOST, TCP_PORT);
Please let me know how I can pass the message generated from the web client to my android client via websocket server.
I am using nodejs for websocket server implementation.
Thanks
From https://datatracker.ietf.org/doc/html/draft-hixie-thewebsocketprotocol-76
The protocol consists of an initial handshake followed by basic message framing, layered over TCP.
So, just opening a Socket on the client side isn't enough. Maybe this will help https://stackoverflow.com/a/4292671
Also take a look at http:// www.elabs.se/blog/66-using-websockets-in-native-ios-and-android-apps chapter Android client
If you really want to implement the WebSocket stuff yourself, take a look at https://stackoverflow.com/a/8125509 and https://www.rfc-editor.org/rfc/rfc6455
I guess I misread your question. Since the connection between the clients and the server already works, you just need to forward the messages.
First, you need to identify the WebSocket client type (Android or Web). Meaning, you immediately send a message what type of client the newly opened WebSocket connection is and store the WebSocket (ws) for that type in the server. Since you have identified and stored each WebSocket connection, you just forward the message to the other type.
For a more specific answer, I need more information.
Should the communication be bidirectional?
Should there be multiple web and Android connections at the same time?

Send data from websocket to socket.io

I used websocket interface to connect to websocket server . what if i want send data that i receive from the websocket server through my websocket interface to client connected to me through http server , should i use socket.io ?
so at the end i will have socket.io attached to to http server and websocket interface to get data and in case of message come will be send to client through socket.io . is that the best setup ?
Code Example :
// Require HTTP module (to start server) and Socket.IO
var http = require('http'),
io = require('socket.io');
var WebSocket = require('ws');
var ws = new WebSocket('ws://localhost:5000');
// Start the server at port 8080
var server = http.createServer(function (req, res) {
// Send HTML headers and message
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.end('<h1>Hello Socket Lover!</h1>');
});
server.listen(8080);
// Create a Socket.IO instance, passing it our server
var socket = io.listen(server);
ws.on('open', function open() {
ws.send('something');
});
ws.on('message', function (data, flags) {
// here the data will be send to socket.io
});
// Add a connect listener
socket.on('connection', function (client) {
// Success! Now listen to messages to be received
client.on('message', function (event) {
console.log('Received message from client!', event);
});
client.on('disconnect', function () {
clearInterval(interval);
console.log('Server has disconnected');
});
});
Yes, your design is correct.
However, one thing that you should keep in mind is take care of sending the message to the correct client after authentication. In my opinion, it is very easy to make this mistake, partially because of the simplicity of messaging using websockets.

Categories

Resources