Say that I use net.createServer in Node.js to create a server like so:
'use strict';
var net = require('net'),
serverPort = 1024,
serverHost = 'localhost',
server;
server = net.createServer(function (socket) {
var whole = '';
console.log('Client connected.');
socket.setEncoding('utf8');
socket.on('data', function (data) {
console.log('Received data.');
whole += data;
});
socket.on('end', function () {
console.log('Client disconnected.');
});
});
server.listen(serverPort, serverHost, function () {
console.log('Server listening at ' + serverHost + ':' + serverPort);
});
I create a connection to this server in an external program and send it a big string. "Received data." is printed 4 times. How can I definitively know when the entire string has been received by the server? The end event is only called when the client disconnects, not when he is done sending his big string.
Related
I want to send a captured image from the raspberry pie client (python) to the server (node.js).
We encoded the image as base64 and sent it back to the server using decoding the base64 as an image, but the image was broken because the file was in a different format.
Here is my code:
client.py
import base64
from PIL import Image
import os, sys
ip = ''
port = 3008
s = socket.socket()
s.connect((ip, port))
image_path = '/home/pi/TCPproject/test.jpg'
if image_path != '':
with open(image_path, "rb") as imageFile:
image_data = base64.b64encode(imageFile.read())
else:
image_data = 'cusdom_image'
s.send(image_data)
s.close()
server.js
var fs = require('fs');
var base64ToImage = require('base64-to-image');
var sockets = [];
var server = net_server.createServer(function(client) {
console.log('Client connection: ');
console.log('local = %s:%s', client.localAddress, client.localPort);
console.log('remote = %s:%s', client.remoteAddress, client.remotePort);
client.setTimeout(500);
client.setEncoding('utf8');
sockets.push(client);
var imageData;
client.on('data', function(data) {
imageData+= data;
});
client.on('end', function() {
console.log('end!')
var decoded = Buffer.from(imageData, 'base64');
fs.writeFile("test.jpg", decoded, function (err) {
if (err) throw err;
else console.log('Saved!');
});
});
client.on('error', function(err) {
console.log('Socket Error: ', JSON.stringify(err));
});
client.on('timeout', function() {
console.log('Socket Timed out');
});
});
server.listen(3008, function() {
console.log('Server listening: ' + JSON.stringify(server.address()));
server.on('close', function(){
console.log('Server Terminated');
});
server.on('error', function(err){
console.log('Server Error: ', JSON.stringify(err));
});
});
function writeData(socket, data){
var success = socket.write(data);
if (!success){
console.log("Client Send Fail");
}
}
Please let me know if encoding, decoding is wrong, or if the TCP socket communication process is wrong, or if there is another problem.
There are multiple problems with the code. On the client side:
s.send(image_data)
This might send image_data but it might only send part of image_data since send is not guaranteed to send everything. Use sendall to send everything or check the return value of send and make sure to send the rest later if not everything was sent at once.
On the server side:
var imageData;
client.on('data', function(data) {
imageData+= data;
});
client.on('end', function() {
console.log('end!')
var decoded = Buffer.from(imageData, 'base64');
If you would have a look at imageData before decoding you would see that it starts with the string undefined and only then the base64 data are following. But all of this is treated as input to the base64 decoder, leading to corrupt data. To fix this initialize imageData:
var imageData = '';
Here is my echo server code
var net = require('net')
var server = net.createServer(function(socket) {
socket.write('Echo server\r\n');
socket.on('data', function(data) {
console.log('recv data: ' + data);
socket.write(data + ' random data');
});
socket.on('end', socket.end);
});
server.listen(1337, '127.0.0.1');
This is the test code
var net = require('net');
var client = new net.Socket();
client.connect(1337, '127.0.0.1', function() {
console.log('Connected');
client.write('Hello, server! Love, Client.');
});
client.on('data', function(data) {
console.log('Received: ' + data);
client.destroy();
});
client.on('close', function() {
console.log('Connection closed');
});
When I first run the client after the server starts, terminal show:
➜ test node client.js
Connected
Received: Echo server
Connection closed
I can see the server has send the data to client in wireshark,but client send a RST packet to server immediately after this packet.
the second is normal
➜ test node client.js
Connected
Received: Echo server
Hello, server! Love, Client. random data
Connection closed
The difference in output is just due to a race condition. Sometimes the server is able to (receive and) send more data before the socket is actually completely closed, other times not.
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.');
});
});
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?
I am trying to write code for server in node.js in which, client running on browser will send some data to server when some ".on" event will occur. Now at server side the task is to receive data coming from client and send that data back to client.
I am using socket.io.
Write now I am doing this as,
Client side:
<p id="ValSlider1"> Curr Val </p>
<input class = "mySlider1" type="range" name="slider" id="slider-0" value="0" min="0" max="100" />
<script>
var socket = io.connect('http://localhost');
$(".mySlider1").change(function() {
var sVal = $(this).val();
socket.emit('ValSlider1', sVal);
console.log('ValSlider1: ' + sVal );
});
socket.on('packet', function (data) {
var valFromServer = data.split('-');
document.getElementById("ValSlider1").innerHTML = valFromServer[0];
document.getElementById("ValSlider2").innerHTML = valFromServer[1];
document.getElementById("ValSlider3").innerHTML = valFromServer[2];
document.getElementById("ValSlider4").innerHTML = valFromServer[3];
$('#container1').html(data);
});
and on server side:
var qs = require('querystring'),
fs = require('fs'),
parser = new require('xml2json'),
urr = require('url'),
app= require('http').createServer(handler).listen(3000),
io = require('socket.io').listen(app);
function handler (req, res) {
var reqObj = urr.parse(req.url, true);
var reqPath = reqObj.pathname;
if ('/' == reqPath ) {
res.writeHead(200, {'Content-Type': 'text/html'});
fs.readFile(__dirname + '/client.html', function(err, data) {if (err) {res.writeHead(500);
return res.end('Errorloadingclient.html');
}
res.end(data);
});
}
};
var slider1, slider2, slider3, slider4 ;
io.sockets.on('connection', function(socket) {
socket.on('ValSlider1', function(data){
slider1 = data ;
socket.emit('packet', data);
console.log("Slider 1 Value: " + data);
});
});
setInterval(function () {
var data = slider1 + "-" + slider2 + "-" + slider3 + "-" + slider4;
socket.emit('packet', data);
console.log(data);
},1000);
});
app.maxConnections = 1;
Now, when communication starts initially two-three slider change values are received by server and printed on console but then the values not get updated, server sends previous values only to client.
Also, if I use socket.emit('ValSlider1', sVal); twice at client side it works better, but why it require emit twice am unable to find, any help will appreciated.
Thanks.
I finally managed to do it in this way:
On server side:
var app = require('http').createServer(handler).listen(3000),
var io = require('socket.io').listen(3001);
var publisher = require('socket.io').listen(app);
On client side:
var socket = io.connect('http://localhost:3001');
var socket2 = io.connect('http://localhost');
The client will send data to server on 'socket'. In response, the server will also send some data on the same port. The server will continuously push data on port 3001 at every second which is received in the client with the ".on('data')" event of server1.