How to initiate websocket Server correctly? - javascript

I've set up a websocket server via php on a local MAMP PRO environment using Ratchet.
$server = IoServer::factory(
new Control(),
81,
'0.0.0.0'
);
Starting the server with root privileges (because I'm unable to get him up with other than root privileges (permission denied) )
php server.php
Establish a connection
telnet 192.168.2.106 81
Trying 192.168.2.106...
Connected to mmm.mrmedia.private.
Answers correctly
php server.php
New connection! (37)
But if I'm trying to connect to the server via JavaScript it's not going through the Handshake (ERR_CONNECTION_REFUSED after a couple of time).
New connection! (48)
Connection 48 sending message "GET / HTTP/1.1
Host: 192.168.2.106:81
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Upgrade: websocket
Origin: http://192.168.2.106
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: de,de-DE;q=0.9,en;q=0.8,en-US;q=0.7,es;q=0.6,fr;q=0.5,it;q=0.4
Sec-WebSocket-Key: RH25+2UD8PQI+0A+VQWn4Q==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
The console outputs the following informations:
TIC TCP Conn Start [24126:0x7fdcc6f47c20]
TIC TCP Conn Event [24126:0x7fdcc6f47c20]: 3
TIC TCP Conn Failed [24126:0x7fdcc6f47c20]: 12:8 Err(-65554)
TIC TCP Conn Cancel [24126:0x7fdcc6f47c20]
Source server.php
use Ratchet\Server\IoServer;
use FluvalEdge\Control;
require dirname(__DIR__) . '/websocket-php-ratchet/vendor/autoload.php';
$server = IoServer::factory(
new Control(),
81,
'0.0.0.0'
);
$server->run();
Source Namespacing FluvalEdge
namespace FluvalEdge;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Control implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
, $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
foreach ($this->clients as $client) {
if ($from !== $client) {
// The sender is not the receiver, send to each client connected
$client->send($msg);
}
}
}
public function onClose(ConnectionInterface $conn) {
// The connection is closed, remove it, as we can no longer send it messages
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
}
Calling the Client-Connection via
initWebsocket('ws://192.168.2.106:81', false, 5000, 5);
Source websocket.js
/**
* inits a websocket by a given url, returned promise resolves with initialized websocket, rejects after failure/timeout.
*
* #param url the websocket url to init
* #param existingWebsocket if passed and this passed websocket is already open, this existingWebsocket is resolved, no additional websocket is opened
* #param timeoutMs the timeout in milliseconds for opening the websocket
* #param numberOfRetries the number of times initializing the socket should be retried, if not specified or 0, no retries are made
* and a failure/timeout causes rejection of the returned promise
* #return {Promise}
*/
function initWebsocket(url, existingWebsocket, timeoutMs, numberOfRetries) {
timeoutMs = timeoutMs ? timeoutMs : 1500;
numberOfRetries = numberOfRetries ? numberOfRetries : 0;
var hasReturned = false;
var promise = new Promise((resolve, reject) => {
setTimeout(function () {
if(!hasReturned) {
console.info('opening websocket timed out: ' + url);
rejectInternal();
}
}, timeoutMs);
if (!existingWebsocket || existingWebsocket.readyState != existingWebsocket.OPEN) {
if (existingWebsocket) {
existingWebsocket.close();
}
var websocket = new WebSocket(url);
websocket.onopen = function () {
if(hasReturned) {
websocket.close();
} else {
console.info('websocket to opened! url: ' + url);
resolve(websocket);
}
};
websocket.onclose = function () {
console.info('websocket closed! url: ' + url);
rejectInternal();
};
websocket.onerror = function () {
console.info('websocket error! url: ' + url);
rejectInternal();
};
} else {
resolve(existingWebsocket);
}
function rejectInternal() {
if(numberOfRetries <= 0) {
reject();
} else if(!hasReturned) {
hasReturned = true;
console.info('retrying connection to websocket! url: ' + url + ', remaining retries: ' + (numberOfRetries-1));
initWebsocket(url, null, timeoutMs, numberOfRetries-1).then(resolve, reject);
}
}
});
promise.then(function () {hasReturned = true;}, function () {hasReturned = true;});
return promise;
};
/*
var ws_host_fluval = "fluvaledge.local";
var ws_port_fluval = "81";
var ws_server_fluval = "";
var ws_url_fluval = "ws://" + ws_host_fluval + ":" + ws_port_fluval + "/" + ws_server_fluval;
try
{
var socket_fluval = new WebSocket(ws_url_fluval);
// Handlerfunktionen definieren
socket_fluval.onopen = function()
{
// Willkommensnachricht an den Server senden
socket_fluval.send("Client hat Verbindung mit fluvaledge hergestellt");
};
socket_fluval.onmessage = function(msg)
{
console.log("Websocket: " + msg.data);
};
socket_fluval.onclose = function(msg)
{
console.log("Verbindung wurde getrennt");
};
}
catch(ex)
{
alert("Exception: " + ex);
}
*/

I think you are confusing plain sockets with WebSockets. Looking at the documentation it looks like you should not use IoServer but WsServer. The first seems to implement plain sockets while the second implements the WebSockets protocol which you are trying to access from Javascript.

Related

nodejs not sending websocket to browser

i made a program that connects my java programm who sends data to my nodejs server using sockets and the nodejs server is supposed to send the received data to the browser using socket.io but there is a problem i do receive the data from java but the node server doesnt send it to the browser here is the code
// Create an instance of the Server and waits for a connexion
net.createServer(function(sock) {
// Receives a connection - a socket object is associated to the connection automatically
console.log('CONNECTED: ' + sock.remoteAddress + ':' + sock.remotePort);
// Add a 'data' - "event handler" in this socket instance
sock.on('data', function(data) {
//data was received in the socket and converting it into string
var textChunk = data.toString('utf8');
io.emit('message', textChunk); //socket.io is supposed to send the data to the browser
console.log(textChunk);
});
// Add a 'close' - "event handler" in this socket instance
sock.on('close', function(data) {
// closed connection
console.log('CLOSED: ' + sock.remoteAddress + ' ' + sock.remotePort);
});
}).listen(PORT, HOST);
You may connect Java side (WebSocketServer) to Javascript side (browser) using github.com/TooTallNate/Java-WebSocket.
Java side:
final class Gateway extends WebSocketServer {
private WebSocket _webSocket;
Gateway( IDataManager dataManager, IConfiguration config) {
super( new InetSocketAddress( <host>, <port> );
new Thread( this ).start();
}
#Override
public void onOpen( WebSocket conn, ClientHandshake handshake ) {
final String request = handshake.getResourceDescriptor();
final String[] req = request.split( "[/=]" );
System.out.printf( "request: %s\n", Arrays.toString( req ));
_webSocket = conn;
...
}
public void publish( ... ) {
final ByteBuffer buffer = ByteBuffer.allocate( ... );
buffer.order( ByteOrder.BIG_ENDIAN );
buffer.putXXX( ... );
buffer.flip();
_webSocket.send( buffer );
}
#Override
public void onMessage( WebSocket conn, String buffer ) {
System.out.printf( "%s\n", buffer );
}
#Override
public void onMessage( WebSocket conn, ByteBuffer buffer ) {
try {
System.out.printf( "%d bytes received from %s",
buffer.remaining(), conn.getRemoteSocketAddress());
if( buffer.position() == buffer.limit()) {
buffer.flip();
}
buffer.order( ByteOrder.BIG_ENDIAN );
final byte xxx = buffer.getXxx();
...
}
catch( final Throwable t ) {
t.printStackTrace();
}
}
#Override
public void onError( WebSocket conn, Exception ex ) {
ex.printStackTrace();
}
#Override
public void onClose( WebSocket conn, int code, String reason, boolean remote ) {
System.out.printf( "code: %d, reason: %s, remote: %s\n", code, reason, remote ? "true" : "false" );
}
}
Javascript side:
var webSocket = new WebSocket(
'ws://' + smoc.PROTOCOL_HOST +
':' + smoc.PROTOCOL_PORT +
'/viewID=' + $scope.viewID );
$scope.webSocket.binaryType = "arraybuffer";
$scope.webSocket.onmessage = function( evt ) {
...
};

unable to connect websocket(wss) from c#

In my application I am connecting chrome extension with windows application using websocket,
Javascript code :
var socket = new WebSocket('ws://172.xx.xxx.xx:11223/');
socket.onopen = function(event)
{
// Web Socket is connected, send data using send()
socket.send("hi..");
};
And C# code :
public static TcpListener Weblistener = null;
public static int selWebSocketPort = 0;
public static void StartListeningSahi()
{
Weblistener = new TcpListener(IPAddress.Parse(ipAddStr), portNumForSelenium);
try{
Weblistener.Start();
int TestingCycle = 100;
// Start listening for connections.
while (TestingCycle > 0){
TcpClient handler = Weblistener.AcceptTcpClient();
// An incoming connection needs to be processed.
lock (ClientSockets.SyncRoot){
if (handler != null){
int i = ClientSockets.Add(new ClientHandler(handler));
((ClientHandler)ClientSockets[i]).Start();
SelWebSocketPort = (handler.Client.RemoteEndPoint as IPEndPoint).Port;
NetworkStream networkStream = handler.GetStream();
Byte[] clientReq = new Byte[handler.Available];
networkStream.Read(clientReq, 0, clientReq.Length);
string headerRequest = Encoding.UTF8.GetString(clientReq);
SendResponseToWebSocket(handler, networkStream, headerRequest);
}
else
continue;
}
}
Weblistener.Stop();
}
catch (Exception e){
Console.WriteLine(e.ToString());
}
}
public static void SendResponseToWebSocket(TcpClient handler, NetworkStream networkStream, string headerRequest)
{
// generate accept key fromm client header request
var key = headerRequest.Replace("ey:", "`")
.Split('`')[1]
.Replace("\r", "").Split('\n')[0]
.Trim();
var responseKey = AcceptKey(ref key);
//create the response for the webclient
var newLine = "\r\n";
var response = "HTTP/1.1 101 Switching Protocols" + newLine
+ "Upgrade: websocket" + newLine
+ "Connection: Upgrade" + newLine
+ "Sec-WebSocket-Accept: " + responseKey + newLine + newLine;
//send respose to the webclient
Byte[] sendBytes = Encoding.ASCII.GetBytes(response);
networkStream.Write(sendBytes, 0, sendBytes.Length);
networkStream.Flush();
selWebSocketPort = (handler.Client.RemoteEndPoint as IPEndPoint).Port;
}
This is working fine for http site. But after that I changed the this javascript line var socket = new WebSocket('ws://172.xx.xxx.xx:11223/'); to var socket = new WebSocket('wss://172.xx.xxx.xx:11223/'); to support https sites, but unable to do so. I am getting below error on chrome -
WebSocket connection to 'wss://172.16.106.22:11223/' failed: WebSocket opening handshake timed out
The handshaking is getting failed as in the request header I am getting some junk value.
Am I missing something ?

Handshake between JS WebSocket and Java

I tried to implement the WebSocket Protocol and connecting a JavaScript WebSocket with a Java WebSocket Server.
The JavaScript part is pretty straight forward and works as expected.
I wrote the Java server myself and read the rfc 6455 page 7 for the correct handshake response. So the server generates the correct response and sends it. I wrote a Java client dummy to make sure it gets send.
But the problem is that the JavaScript / Browser seems not to receive the handshake response and kills the request after some seconds (but does not close the tcp socket).
Here is the handshake:
Client
GET / HTTP/1.1
Host: 127.0.0.1:4455
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://localhost
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Server
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
HTML JavaScript
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Socket testing - Client</title>
</head>
<body>
<div id="container"></div>
<script type="text/javascript">
var socket = new WebSocket('ws://127.0.0.1:4455');
socket.addEventListener("error",function(e){
console.log("an error ocurred: ",e)
})
socket.addEventListener("close",function(e){
console.log("the connection was closed: ",e)
})
socket.addEventListener("open",function(e){
console.log("the connection was opened: ",e)
})
socket.addEventListener("message",function(e){
console.log("recieved a message: ",e)
})
</script>
</body>
</html>
Java (excerpt)
public class SocketHandlerWebSocketLevel extends SocketHandler {
private HashMap<String, String> connectionHeaders;
private InputStreamReader stringReader;
private OutputStreamWriter stringWriter;
public SocketHandlerWebSocketLevel(Socket socket) {
super(socket);
connectionHeaders = new HashMap<String, String>();
try {
stringReader = new InputStreamReader(s.getInputStream());
} catch (IOException e) {
e.printStackTrace();
close();
print("could not get the input stream");
return;
}
try {
stringWriter = new OutputStreamWriter(s.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
close();
print("could not get the output stream");
return;
}
}
#Override
public void run() {
print("Started handler");
char b;
String buffer = "";
try {
mainLoop: while (true) {
while (stringReader.ready() || buffer.length() == 0) {
if ((b = (char) stringReader.read()) != -1) {
buffer += b;
} else {
break mainLoop;
}
}
gotMessage(buffer);
buffer = "";
}
} catch (IOException e) {
close();
print("connection was killed remotly, could not read the next byte");
return;
}
close();
print("connection was closed remotely, stopped Handler, closed socked");
}
private void gotMessage(String message) {
if (connectionHeaders.size() == 0) {
connectionHeaders = parseHttpHeader(message);
handshakeResponse();
} else {
print(message);
}
}
private void handshakeResponse() {
/*
taken from: https://www.rfc-editor.org/rfc/rfc6455#page-7
For this header field, the server has to take the value (as present
in the header field, e.g., the base64-encoded [RFC4648] version minus
any leading and trailing whitespace) and concatenate this with the
Globally Unique Identifier (GUID, [RFC4122]) "258EAFA5-E914-47DA-
95CA-C5AB0DC85B11" in string form, which is unlikely to be used by
network endpoints that do not understand the WebSocket Protocol. A
SHA-1 hash (160 bits) [FIPS.180-3], base64-encoded (see Section 4 of
[RFC4648]), of this concatenation is then returned in the server's
handshake.
Concretely, if as in the example above, the |Sec-WebSocket-Key|
header field had the value "dGhlIHNhbXBsZSBub25jZQ==", the server
would concatenate the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
to form the string "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-
C5AB0DC85B11". The server would then take the SHA-1 hash of this,
giving the value 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6
0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. This value is
then base64-encoded (see Section 4 of [RFC4648]), to give the value
"s3pPLMBiTxaQ9kYGzzhZRbK+xOo=". This value would then be echoed in
the |Sec-WebSocket-Accept| header field.
*/
String secWebSocketKey, secWebSocketAccept, GUID, template, merged, toSend;
secWebSocketKey = connectionHeaders.get("Sec-WebSocket-Key");
GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
template = "HTTP/1.1 101 Switching Protocols\nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Accept: %s\nSec-WebSocket-Protocol: chat\n";
// combine secWebSocketKey and the GUID
merged = secWebSocketKey + GUID;
print("merged: " + merged);
// convert to byte[]
byte[] asBytes = merged.getBytes();
print("asBytes: " + Arrays.toString(asBytes));
// SHA-1 hash
byte[] sha1 = SHA1Hash(asBytes);
print("sha1: " + Arrays.toString(sha1));
// base64 encode
byte[] base64 = base64Encode(sha1);
print("base64: " + Arrays.toString(base64));
// reconvert to string to put it into the template
secWebSocketAccept = new String(base64);
toSend = String.format(template, secWebSocketAccept);
print(toSend);
try {
stringWriter.write(toSend, 0, toSend.length());
stringWriter.flush();
} catch (IOException e) {
print("hanshake sending failed!");
}
}
private HashMap<String, String> parseHttpHeader(String h) {
HashMap<String, String> fields = new HashMap<String, String>();
String[] rows = h.split("\n");
if (rows.length > 1) {
fields.put("Prototcol", rows[0]);
Pattern pattern = Pattern.compile("^([^:]+): (.+)$");
for (int i = 1; i < rows.length; i++) {
Matcher matcher = pattern.matcher(rows[i]);
while (matcher.find()) {
if (matcher.groupCount() == 2) {
fields.put(matcher.group(1), matcher.group(2));
}
}
}
}
return fields;
}
private byte[] SHA1Hash(byte[] bytes) {
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
return null;
}
md.update(bytes);
return md.digest();
}
private byte[] base64Encode(byte[] bytes) {
byte[] encodedBytes = Base64.getEncoder().encode(bytes);
return encodedBytes;
}
Where might be my error? What could be missing, maybe a "message end" symbol?
Note that I don't want to use a framework.
The solution was simple. I just used Wireshark to debug this whole thing: I just forgot the carriage return.
The correct string in the Java class would be:
template = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\nSec-WebSocket-Protocol: chat\r\n\r\n";
Until this modification the browser is not able to interpret it as HTTP data in the TCP package.

How to connect to a websocket from a different server?

I have server A "windows 7 Pro" where I installed node.js and ran it using this command node ws_server.js following the instructions here
From server B "Windows Server 2008 R2" running Apache 2.4/php 5.6.13 I want to connect to the ws_server on Server A.
on **Server B* I have a script called websocket.php with the code below
<script>
$(function() {
var WebSocketClient = require('websocket').client;
var client = new WebSocketClient();
client.on('connectFailed', function(error) {
console.log('Connect Error: ' + error.toString());
});
client.on('connect', function(connection) {
console.log('WebSocket Client Connected');
connection.on('error', function(error) {
console.log("Connection Error: " + error.toString());
});
connection.on('close', function() {
console.log('echo-protocol Connection Closed');
});
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log("Received: '" + message.utf8Data + "'");
}
});
function sendNumber() {
if (connection.connected) {
var number = Math.round(Math.random() * 0xFFFFFF);
connection.sendUTF(number.toString());
setTimeout(sendNumber, 1000);
}
}
sendNumber();
});
client.connect('ws://ServerA:8080/', 'echo-protocol');
});
</script>
But for some reason I get this error in the console.
ReferenceError: require is not defined
Do I need to take files from the nodejs folder from server A and include it in the client script? if so which files do I need to include?
Note: I have included jQuery files as well
EDITED
this is my client code
<script>
"use strict";
// Initialize everything when the window finishes loading
window.addEventListener("load", function(event) {
var status = document.getElementById("status");
var url = document.getElementById("url");
var open = document.getElementById("open");
var close = document.getElementById("close");
var send = document.getElementById("send");
var text = document.getElementById("text");
var message = document.getElementById("message");
var socket;
status.textContent = "Not Connected";
url.value = "ws://serverB:8080";
close.disabled = true;
send.disabled = true;
// Create a new connection when the Connect button is clicked
open.addEventListener("click", function(event) {
open.disabled = true;
socket = new WebSocket(url.value, "echo-protocol");
socket.addEventListener("open", function(event) {
close.disabled = false;
send.disabled = false;
status.textContent = "Connected";
});
// Display messages received from the server
socket.addEventListener("message", function(event) {
message.textContent = "Server Says: " + event.data;
});
// Display any errors that occur
socket.addEventListener("error", function(event) {
message.textContent = "Error: " + event;
});
socket.addEventListener("close", function(event) {
open.disabled = false;
status.textContent = "Not Connected";
});
});
// Close the connection when the Disconnect button is clicked
close.addEventListener("click", function(event) {
close.disabled = true;
send.disabled = true;
message.textContent = "";
socket.close();
});
// Send text to the server when the Send button is clicked
send.addEventListener("click", function(event) {
socket.send(text.value);
text.value = "";
});
});
</script>
require is a library used by nodejs, it's not present in window naturally,. I believe you are trying to use a code that you had been using in a nodejs environment.
In order to create the socket in a web based environment, checkout the WebSocket reference.
WebSockets are implemented in most latest browsers versions and you create them as follows:
var exampleSocket = new WebSocket("ws://www.example.com/socketserver", "protocolOne");
Taxicala answer is correct, you dont need require.
I think that you could try this piece of code in order to see if the sockets are working
var ws = new WebSocket('wss://ServerA:8080/', 'echo-protocol');
ws.onopen = function () {
console.log('socket connection opened properly');
ws.send("Hello World"); // send a message
console.log('message sent');
};
ws.onmessage = function (evt) {
console.log("Message received = " + evt.data);
};
ws.onclose = function () {
// websocket is closed.
console.log("Connection closed...");
};
In order to avoid the security error you should create the web socket server as https instead of http, This is the code that you provided in the related links, it is adapted to generate a secure server that allow CORS for all sites and methods, its only for testing proposes.
Note that you need to generate the certificates, and store it in a folder named certs2, if you need instructions to create the certs just google a little, there are a lot of great answer for that.
//CUSTOM
var WebSocketServer = require('websocket').server;
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('./certs2/key.pem'),
cert: fs.readFileSync('./certs2/key-cert.pem')
};
var server = https.createServer(options, function (req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.writeHead(404);
res.end();
});
// END CUSTOM
// START YOUR CODE....
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.');
});
});
I had faced socket hangup error.
const WebSocket = require('ws');
const ws = new WebSocket('wss://127.0.0.1:8080');
events.js:183
throw er; // Unhandled 'error' event
^
Error: socket hang up
at TLSSocket.onHangUp (_tls_wrap.js:1137:19)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:111:20)
at TLSSocket.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
And I could fix that by modifying websocket connection code.
const ws = new WebSocket('ws://127.0.0.1:8080/ws');

Websocket server with ssl support (using websocket.io)

I have a simple Websocket server using node.js and websocket.io
var ws = require('websocket.io')
, server = ws.listen(8000);
server.on('connection', function (socket) {
console.log("connected");
socket.on('message', function (message) {
on_message_callback(socket, message);
});
socket.on('close', function () {
on_close_callback(socket);
});
});
And this is a major part of client:
const HOST = "wss://127.0.0.1:8000/";
var websocket = new WebSocket(HOST);
websocket.onopen = function(evt) { ... };
websocket.onclose = function(evt) { ... },
websocket.onerror = function(evt) { ... };
websocket.onmessage = function(evt) { ... };
(I've tested it with wss://echo.websocket.org:443 and works as desired)
Works for HTTP pages as desired. Problem is that I need to work under HTTPS pages, too. I not able to "upgrade" my code to make it work. Can anyone help me? I haven't found any tutorial for websocket.io (I want to keep using the same technologies).
I'm also not sure how to handle certificates. I can only generate self-signed. What for this case? When I create them, I have to import them manually to each browser, so they'll allow this communication?
Thank you.
Finally figured out solution (using Worlize/websocket-node)
const PORT = 8000;
const SUBPROTOCOL = 'sub-protocol';
var WebSocketServer = require('websocket').server;
var https = require('https');
var fs = require('fs');
// Private key and certification (self-signed for now)
var options = {
key: fs.readFileSync('cert/server.key'),
cert: fs.readFileSync('cert/server.crt')
};
// callback function is called only when localhost:8000 is accessed via https protocol
var server = https.createServer(options, function(request, response) {
// it sends 404 response so browser stops loading, otherwise it keeps loading
console.log((new Date()) + ' Received HTTP(S) request for ' + request.url);
response.writeHead(404);
response.end();
});
// bind server object to listen to PORT number
server.listen(PORT, function() {
console.log((new Date()) + ' Server is listening on port ' + PORT);
});
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;
}
// If autoAcceptConnections is set to false, a request event will be emitted
// by the server whenever a new WebSocket request is made
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;
}
// accepts connection and return socket for this connection
var connection = request.accept(SUB_PROTOCOL, request.origin);
console.log((new Date()) + ' Connection accepted.');
// when message is received
connection.on('message', function(message) {
// echo
connection.send(connection, message.utf8Data);
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});

Categories