I use nodejs net module send socket like this
var client = new net.Socket();
client.connect('8888','127.0.0.1',function(){
for(var i=0; i < 3; i++){
var postData = {};
postData.index = 0;
client.write(JSON.stringify(postData));
}
})
if I wait 200ms after send every packet , then server will recv 3 packet , and parse json normal , like this
{"index":0}
{"index":0}
{"index":0}
but if I send this data in for loop block , then server just recv 1 packet , seem like these:
{"index":0} {"index":0} {"index":0}
any solutions ? Thanks!
Related
i made i client tcp socket with c# and its work without any problem with c# server too
first before i send data to the client i sent the header contain the data length adn some other
now i tried same client code with nodeJs server TCP i got some issuse with Buffer size in nodeJs
first this is my header
function writeInt(stream, int){
var bytes = new Array(5)
bytes[0] = 2
bytes[1] = int >> 24
bytes[2] = int >> 16
bytes[3] = int >> 8
bytes[4] = int
bytes[5] = 0
stream.write( Buffer.from(bytes))
}
//1,2,3,4 the size of the buffer
if i want to send message to client i use
var buf = Buffer.from("HELLO THIS IS A MESSAGE FROM SERVER");
writeInt(sock, buf.length)
sock.write(buf);
that's work because i use string but when i tried to send integer i got issuse
like
var buf = Buffer.from([1,2222,999,666]);
writeInt(sock, buf.length)
sock.write(buf);
first thing the length of the buffer its wrong when i use buf.length it's return 4!!
i tried other method found it in NodeJs website like
let buf = Buffer.alloc(3); // Init buffer without writing all data to zeros
buf.writeUInt16BE(220);
and
let buf = Buffer.allocUnsafe(2);
buf.writeUInt16BE(1234);
all those return wrong buffer length
or buffer length not like i sent with function writeInt
that's happen only with Integer when i sent string its work without any issuse
I count the number of online websockets via onConnection and onDisconnect events:
const socketIo = require('socket.io');
var on_connect = 0;
var on_disconnect = 0;
var port = 6001;
var io = socketIo(port, {
pingTimeout: 5000,
pingInterval: 10000
});
//I have only one NameSpace and root NS is not used
var ns1 = io.of('ns1');
ns1
.on('connection', function (socket) {
on_connect += 1;
socket.on('disconnect', function (reason) {
on_disconnect += 1;
});
});
...
var online = on_connect - on_disconnect;
...
But online value not equal io.engine.clientsCount value.
And over time the difference between online value and io.engine.clientsCount value is growing up.
Why this is happens?
What is needed to make to fix this?
on_connect and on_disconnect variables are updates in the callback events, whereas the online variable is not recalculated. So you will need to recalculate the online variable every time the other variable change.
It might be easier to use only one variable to count connections. Increment it on connection, and decrement it on disconnect. That's how I keep track of the number of connections. Then there isn't a need to calculate it every time its value is needed.
Also, the line that states var online = on_connect - on_disconnect; Is occurring before either is modified... That's what #gvmani is trying to tell you.
Here's an example of some of what I'm doing. The code below sets up to listen for connections & disconnections and maintains a count of current connections. I should note that I'm not using a namespace like the OP, but the counting portion is what's of importance. I'll also note that I use connCount > 0 in the send() function. Which in my application is used to broadcast to all connected clients.
/* ******************************************************************** */
// initialize the server
const http = require('http');
const server = http.createServer();
// Socket.io listens to our server
const io = require('socket.io').listen(server);
// Count connections as they occur, decrement when a client disconnects.
// If the counter is zero then we won't send anything over the socket.
var connCount = 0;
// A client has connected,
io.on('connection', function(socket) {
// Increment the connection counter
connCount += 1;
// log the new connection for debugging purposes.
console.log(`on connect - ${socket.id} ${connCount}`);
// The client that initiated the connection has disconnected.
socket.on('disconnect', function () {
connCount -= 1;
console.log(`on disconnect - ${socket.id} ${connCount}`);
});
});
// Start listening...
server.listen(3000);
// Send something to all connected clients (a broadcast) the
// 'channel' will indicate the destination within the client
// and 'data' becomes the payload.
function send(channel, data) {
console.log(`send() - channel = ${channel} payload = ${JSON.stringify(data)}`);
if(connCount > 0) io.emit(channel, {payload: data});
else console.log('send() - no connections');
};
I'm now trying to send bytes continuously from node.js(server) to Android(client). Let me show the code example.
var net = require('net');
var server = net.createServer(function(c){
c.on('data', function(data){
if(data == 'foo'){
for(var i = 1; i <= 255; i++){
var byteData = makeBytedata();
c.write(byteData);
wait(100)
}
}
});
});
This code does not works fine because it sometimes combines byteData to one packet. Does anyone have solution to send bytes separately?
net.createServer create TCP server, TCP does not send messages separately. TCP is a stream protocol, which means that when you write bytes to the socket, you get the same bytes in the same order at the receiving end.
One work around: define a format for your message, so that your client can determine the beginning and end of a message within the socket stream. For example, you could use a \n to mark the end of a message.
for(var i = 1; i <= 255; i++){
var byteData = makeBytedata();
c.write(byteData + '\n');
}
Then the client could separate them by \n.
The other way could be to use UDP/Dgram
var dgram = require("dgram"),
server = dgram.createSocket('udp4');
server.on("message", function(msg, rinfo) {
// send message to client
});
Ok, I have an express-powered API where I also have socket.io running to receive/send realtime events...all works just dandy. I need to cluster my app. I set everything up based on the below code. I spin up workers, they get connections and everything works, except the fact that now I can't "blast" to all socket.io connections. Here is the setup (taken from this):
var express = require('express'),
cluster = require('cluster'),
net = require('net'),
sio = require('socket.io'),
sio_redis = require('socket.io-redis');
var port = 3000,
num_processes = require('os').cpus().length;
if (cluster.isMaster) {
// This stores our workers. We need to keep them to be able to reference
// them based on source IP address. It's also useful for auto-restart,
// for example.
var workers = [];
// Helper function for spawning worker at index 'i'.
var spawn = function(i) {
workers[i] = cluster.fork();
// Optional: Restart worker on exit
workers[i].on('exit', function(worker, code, signal) {
console.log('respawning worker', i);
spawn(i);
});
};
// Spawn workers.
for (var i = 0; i < num_processes; i++) {
spawn(i);
}
// Helper function for getting a worker index based on IP address.
// This is a hot path so it should be really fast. The way it works
// is by converting the IP address to a number by removing the dots,
// then compressing it to the number of slots we have.
//
// Compared against "real" hashing (from the sticky-session code) and
// "real" IP number conversion, this function is on par in terms of
// worker index distribution only much faster.
var workerIndex = function (ip, len) {
var _ip = ip.split(/['.'|':']/),
arr = [];
for (el in _ip) {
if (_ip[el] == '') {
arr.push(0);
}
else {
arr.push(parseInt(_ip[el], 16));
}
}
return Number(arr.join('')) % len;
}
// Create the outside facing server listening on our port.
var server = net.createServer({ pauseOnConnect: true }, function(connection) {
// We received a connection and need to pass it to the appropriate
// worker. Get the worker for this connection's source IP and pass
// it the connection.
var worker = workers[worker_index(connection.remoteAddress, num_processes)];
worker.send('sticky-session:connection', connection);
}).listen(port);
} else {
// Note we don't use a port here because the master listens on it for us.
var app = new express();
// Here you might use middleware, attach routes, etc.
// Don't expose our internal server to the outside.
var server = app.listen(0, 'localhost'),
io = sio(server);
// Tell Socket.IO to use the redis adapter. By default, the redis
// server is assumed to be on localhost:6379. You don't have to
// specify them explicitly unless you want to change them.
io.adapter(sio_redis({ host: 'localhost', port: 6379 }));
// Here you might use Socket.IO middleware for authorization etc.
// Listen to messages sent from the master. Ignore everything else.
process.on('message', function(message, connection) {
if (message !== 'sticky-session:connection') {
return;
}
// Emulate a connection event on the server by emitting the
// event with the connection the master sent us.
server.emit('connection', connection);
connection.resume();
});
}
So I connect from various machines to test concurrency, workers do their thing and all is good, but when I get an IO connection, I'm logging the TOTAL "connected" count and it's always 1 per instance. I need a way to say
allClusterForks.emit(stuff)
I get the connection on the correct worker pid, but "ALL CONNECTIONS" always returns 1.
io.on('connection', function(socket) {
console.log('Connected to worker %s', process.pid);
console.log("Adapter ROOMS %s ", io.sockets.adapter.rooms);
console.log("Adapter SIDS %s ", io.sockets.adapter.sids);
console.log("SOCKETS CONNECTED %s ", Object.keys(io.sockets.connected).length);
});
I can see the subscribe/unsubscribe coming in using Redis MONITOR
1454701383.188231 [0 127.0.0.1:63150] "subscribe" "socket.io#/#gXJscUUuVQGzsYJfAAAA#"
1454701419.130100 [0 127.0.0.1:63167] "subscribe" "socket.io#/#geYSvYSd5zASi7egAAAA#"
1454701433.842727 [0 127.0.0.1:63167] "unsubscribe" "socket.io#/#geYSvYSd5zASi7egAAAA#"
1454701444.630427 [0 127.0.0.1:63150] "unsubscribe" "socket.io#/#gXJscUUuVQGzsYJfAAAA#"
These are connections from 2 different machines, I would expect by using the socket io redis adapter that these subscriptions would be coming in on the same redis connection, but they are different.
Am I just totally missing something? There's a surprising lack of documentation/articles out there for this that aren't either completely outdated/wrong/ambiguous.
EDIT:
Node v5.3.0
Redis v3.0.6
Socket.io v1.3.7
So if anyone comes across this, I figured out that actually "looking" at the counts of connected sockets across processes is not a thing, but broadcasting or emitting to them is. So I've basically just been "testing" for no reason. All works as expected. I WILL be rewriting the socket.io-redis adapter to allow checking counts across processes.
There was a pull request a few years ago to implement support for what I was trying to do. https://github.com/socketio/socket.io-redis/pull/15 and I might try cleaning that up and re-submitting.
I am creating a node application that will send UDP packets to another machine. Everything appears to work fine when packets are sent about 100/second. When that number gets higher 500/second the packets stop sending. I don't think they are being droped as Wireshark does not show them leaving my computer.
const dgram = require("dgram");
var sent = 0;
var server = dgram.createSocket("udp4");
function sendCommand(text){
// Put command into a buffer
var buffer = new Buffer(text);
// Send the command
server.send(buffer, 0, buffer.length, 12345, 19.5.6.45, (err) => {
sent++;
});
}
The sendCommand() function is what is called internally. Like I said at 100 calls per second no problem. When it gets higher it just stops working.
The "sent" var stops incrementing so this leads me to think node dgram is faulty and server.send() is not firing correctly. It doesn't seem to recover unless I restart the program.
This is my first time posting on Stack Overflow, I apologise if I did anything wrong.
Edit:
Here is where the function is firing from.
// Loop through the channels
for (var i = 0; i < ids.length; i++) {
// Check if the channel is locked
if (!toBool(data.locks[i])) {
// Send the UDP command
sendCommand(ids[i]);
}
}