I have an angularjs website with NodeJS socket methods as a client, and a NodeJS application as a server.
Data is being passed from the server to the client through socket events. The problem is that after working fine for about 5 minutes, intermittently data that is successfully being sent from the NodeJS server is being received as 'null' in the website, thus giving me the following error:
angular.js:11598 TypeError: Cannot read property '<fieldName>' of null
at ecabsAngular.js:42
at angular.js:12149
at angular.js:12137
at angular.js:12137
at Object.<anonymous> (angular.js:12837)
at l.$digest (angular.js:14222)
at l.$apply (angular.js:14493)
at Socket.<anonymous> (ecabsAngular.js:275)
at Socket.Emitter.emit (socket.io-1.2.0.js:1)
at Socket.onevent (socket.io-1.2.0.js:1)
Do you have any idea what is causing this and how this can be solved?
Thanks in advance!
Edit:
This is the code that is crashing on the client side (on the website)
(function(){
var app = angular.module('Module', []);
app.controller('MainCtrl', ['$scope', '$window', function($scope, $window){
$scope.bookings = [];
socket.on('updateBooking', function(booking){
$scope.loadAllocations();
for (var i=0; i<$scope.bookings.length; i++) {
if ($scope.bookings[i].CRMBookingID == booking.CRMBookingID) {
$scope.$apply(function(){
$scope.bookings[i] = booking;
});
}
}
});
}
]);
})();
This is the code from the NodeJS (server):
var app = require('express')();
var http = require('http');
http.globalAgent.maxSockets = 200;
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var sql = require('mssql');
server.listen(3000);
app.post('/updatebooking', function(request, response) // receive web service request
{
response.writeHeader(200, {"Content-Type": "text/plain"}); // build response header
response.end(); // end the response
request.on('data', function(changes)
{
try{
var c = JSON.parse(changes.toString()); // parse data received
var connection = new sql.Connection(config); // create DB connection
connection.connect(function (err) // connect to the database
{
if (err!=null) { logger.error('Update booking connection error: ' + c + ' ' + err); }
var request = new sql.Request(connection); // create SQL request
request.stream = true;
try{
var sqlquery = <sqlquery>; // build SQL query
logger.trace("Executing SP in DB: " + sqlquery);
request.query(sqlquery); // execute SP
request.on('row', function (row) // once committed send to the client (website)
{
logger.trace("Updated booking with Reference ID " + row.Ref + " " + sqlquery);
io.emit('updateBooking', row); // sending data
})
request.on('error', function(err) {
logger.error('Update booking SP request error: ' + sqlquery + err);
});
}catch( e){
logger.error('Update booking request error' + sqlquery + ' ' + e);
}
});
} catch(e)
{
var c = JSON.parse(changes.toString());
logger.error('Update booking error for: ' + c + ' ' +e);
}
connection.on('error', function(err) {
logger.error('Update error connection: ' + err);
});
});
});
Related
I am using a http server with a socket connection , when http request hits, socket connection sends message to different client which performs a http request after this http response the client replies to the message and and response of initial http request is send.
My problem is first http request sometimes get response successfuly and sometimes not, I think there is a sync problem, how to solve it.
code for creating socket and httpserver -
const app = require('express')()
bodyParser = require('body-parser')
app.use(bodyParser.json())
const net = require('net');
var client;
var res1,currentReq;
//----------------------------------------------------------------------------
// http requests listener
//----------------------------------------------------------------------------
app.listen(8001, () => console.log('Http server listening on port 8001'));
//----------------------------------------------------------------------------
// http requests handling
//----------------------------------------------------------------------------
app.post('/makeCall', (req, res) => {
console.log('sd' + req.body)
res1 = res;
currentReq='makeCall';
console.log('{"route":"/api/makeCall","data":{"product_id":"' + req.body.product_id + '","destination":"' + req.body.destination + '"}}');
client.write('{"route":"/api/makeCall","data":{"product_id":"' + req.body.product_id + '","destination":"' + req.body.destination + '"}}');
});
//----------------------------------------------------------------------------
// Establishing tcp connection for incoming requests
//----------------------------------------------------------------------------
var server = net.createServer(function(connection) {
console.log ('client has connected successfully!');
client = connection;
client.on('data',function(data){
switch(currentReq)
{
case 'makeCall' :
console.log('send make call response');
res1.end(data);
break;
}
console.log(data.toString());
//res1.end(data);
});
connection.pipe(connection);
});
//----------------------------------------------------------------------------
// listener for tcp connections
//----------------------------------------------------------------------------
server.listen(8000, function() {
console.log('server for localhost is listening on port 8000');
console.log('server bound address is: ' + server.address ());
});
code for client to which socket connects -
tcpClient.on('connect',function(){
logger.info("[%s] , Connected to the server at %s:%s",__file,CONFIG.tcp_server_host,CONFIG.tcp_server_port);
logger.info("[%s] , TCP client info %s",__file,tcpClient.address().address);
});
// Handle data event
tcpClient.on('data',function(data){
logger.info('[%s] , Data recevied',__file);
// Convert the Buffer to JSON object
var reqInfo;
reqInfo = JSON.parse(data.toString());
if(reqInfo!=null){
switch(reqInfo.route){
case '/api/makeCall':;
var product_id = reqInfo.data.product_id;
var destination = reqInfo.data.destination;
var test = {};
var source;
var myJSONObject = {'product_id':product_id};
MongoClient.connect(url, function(err, db) {
var dbo = db.db("mapping");
dbo.collection("mapping").findOne({"id":product_id},function(err,result)
{
if(err)
{
throw err;
}
JSON.stringify(result);
sourceDB = result.source;
// Set the options for HTTPS request
options.method = "POST";
options.url = "url";
options.json = true;
options.auth = {
user: '123',
password: '123'
};
options.body = {"Source": sourceDB,"Destination": destination} ;
logger.info('[%s] , HTTPS request options : %o',__file,options);
request(options,function(error,res1,body){
tcpClient.write('Sending data to Falcon');
});
});
});
I have two files one is test.html which is:
<script src="js/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
$(function () {
// if user is running mozilla then use it's built-in WebSocket
window.WebSocket = window.WebSocket || window.MozWebSocket;
var connection = new WebSocket('ws://localhost:8080/');
connection.onopen = function () {
// connection is opened and ready to use
alert('connection Open');
};
connection.onerror = function (error) {
// an error occurred when sending/receiving data
alert('Error');
};
connection.onmessage = function (message) {
alert('Message');
};
});
</script>
And one nodejs file which is
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,
autoAcceptConnections: false
});
function originIsAllowed(origin) {
return true;
}
wsServer.on('request', function(request) {
if (!originIsAllowed(request.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) {
console.log(message);
connection.sendBytes(message);
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
While I am trying to connect with web-socket with my HTML file its give me an error which is
Firefox can’t establish a connection to the server at ws://localhost:8080/
It should be able to find and connect to the server but the server will reject your request and shutdown because of request.accept('echo-protocol', request.origin) in your server file.
Check the log of you nodejs command prompt.
To fix this just modify
var connection = new WebSocket('ws://localhost:8080/');
to
var connection = new WebSocket('ws://localhost:8080/', 'echo-protocol');
I am developing a simple node api/server, that uses websockets, specifically ZeroMQ. However when sending/requesting data, I receive the following error:
RangeError: Invalid status code: 0 at ServerResponse.writeHead (_http_server.js:192:11)
var express = require('express');
var app = express();
var bodyParser = require("body-parser");
var server_port = "3000";
/** app settings **/
var zeromq = require("zeromq");
var socket = zeromq.socket("req");/* sends request */
var protocol = "tcp://";
var ip = "192.000.0.000"; //server
var socket_port = "9998";
var url = protocol + ip + ":" + socket_port;
app.use(bodyParser());
/** paths **/
app.post('/request', function (request, response) {
var command = request.body;
//connect to port
socket.connect(url, function (error) {
if (error) {
console.log("connection error : ", error);
process.exit(0);
}
});
//response to front end
socket.send(JSON.stringify(command));
//recieve request
socket.on('message', function (message) {
//output message to console
console.log("Recieved message # : " + (new Date().toDateString()) + " : " + message.toString());
//send response
response.setHeader('Content-Type', 'text/plain');
response.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');
response.status(200).send(message);
});
});
/** start app **/
app.listen(server_port);
console.log("Server started on port: " + server_port);
CODE UPDATED:
Now I am getting:
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11)
I'm guessing that you are sending the status 0. Try using
res.status(200).send(<body>);
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');
I'm working with a windows app and trying to connect it to node server.
I'm using web sockets in the windows app and and 'websocket' from npm for node.
I'm have trouble connecting the two it seems like there connecting but when I try to send information across(simple hello world string) nothing happens.
I have a simple javascript windows app.
In my default.html there is just a simple button:
<button onclick="Check()">Check status</button>
In the default.js I have the Check function which is:
function Check()
{
var host = "ws://192.168.201.91:8080";
try
{
socket = new WebSocket(host);
socket.onopen = function (openEvent)
{
console.log("Sockets open");
socket.send("Hello, world");
console.log("Socket state: " + socket.readyState);
console.log("Message is sent to: " + socket.url);
};
socket.onerror = function (errorEvent)
{
console.log(" 'WebSocket Status:: Error was reported';")
};
socket.onclose = function (closeEvent)
{
console.log("WebSocket Status:: Socket Closed");
};
socket.onmessage = function (messageEvent)
{
console.log(socket.toString);
var received_msg = messageEvent.data;
console.log("Message recieved: " + received_msg);
}
}
catch(exception)
{
if (window.console)
console.log(exception);
}
}
socket.readyState return me 1 which states a connection is made and the socket is ready for sending!
My node server then looks like this:
#!/usr/bin/env node
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: true
});
console.log("Here wsServer");
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;
//}
console.log("Here");
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);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
I have taken out any security checks as I just want the message to send to the server.
But this is not happening and I dont know why! Any help would be greatly appreciated.
Edit --
Just thought it should be possible to send information to see if it hits the sever but i am just not sure on a windows app what the ip is! If I can tell my node server to send information that will at least let me know that a channel is open.
Any ideas how to get the ip of a windows app through javascript?