Send commands over socket, but wait every time for response (Node.js) - sockets

I need to send several commands over telnet to a server. If I try to send them without a time delay between every command, the server freaks out:
var net = require('net');
var conn = net.createConnection(8888, 'localhost');
conn.on('connect', function() {
conn.write(command_1);
conn.write(command_2);
conn.write(command_3);
//...
conn.write(command_n);
})
I guess the server needs some time to respond to command n before I send it command n+1. One way is to write something to the log and fake a "wait":
var net = require('net');
var conn = net.createConnection(8888, 'localhost');
conn.on('connect', function() {
console.log('connected to server');
console.log('I'm about to send command #1');
conn.write(command_1);
console.log('I'm about to send command #2');
conn.write(command_2);
console.log('I'm about to send command #3');
conn.write(command_3);
//...
console.log('I'm about to send command #n');
conn.write(command_n);
})
It might also be the fact that conn.write() is asynchronous, and putting one command after another doesn't guranty the correct order??
Anyway, what is the correct pattern to assure correct order and enough time between two consecutive commands, for the server to respond?

First things first: if this is truly a telnet server, then you should do something with the telnet handshaking (where terminal options are negotiated between the peers, this is the binary data you can see when opening the socket).
If you don't want to get into that (it will depend on your needs), you can ignore the negotiation and go straight to business, but you will have to read this data and ignore it yourself.
Now, in your code, you're sending the data as soon as the server accepts the connection. This may be the cause of your troubles. You're not supposed to "wait" for the response, the response will get to you asynchronously thanks to nodejs :) So you just need to send the commands as soon as you get the "right" response from the server (this is actually useful, because you can see if there were any errors, etc).
I've tried this code (based on yours) against a device I've got at hand that has a telnet server. It will do a login and then a logout. See how the events are dispatched according to the sever's response:
var net = require('net');
var conn = net.createConnection(23, '1.1.1.1');
var commands = [ "logout\n" ];
var i = 0;
conn.setEncoding('ascii');
conn.on('connect', function() {
conn.on('login', function () {
conn.write('myUsername\n');
});
conn.on('password', function () {
conn.write('myPassword\n');
});
conn.on('prompt', function () {
conn.write(commands[i]);
i++;
});
conn.on('data', function(data) {
console.log("got: " + data + "\n");
if (data.indexOf("login") != -1) {
conn.emit('login');
}
if (data.indexOf("password") != -1) {
conn.emit('password');
}
if (data.indexOf(">#") != -1) {
conn.emit('prompt');
}
});
});
See how the commands are in an array, where you can iteratively send them (the prompt event will trigger the next command). So the right response from the server is the next prompt. When the server sends (in this case) the string ># another command is sent.
Hope it helps :)

The order of writes is guaranteed. However:
You must subscribe to data event. conn.on('data', function(data)
{}) will do.
You must check return values of writes - if a write
fails, you must wait for 'drain' event. So you should check if any
write really fails and if it does then fix the problem. If it
doesn't - then you can leave current dirty solution as is.
You
must check if your server supports request piplining (sending
multiple requests without waiting for responses). If it doesn't -
you must not send next request before receiving a data event after
the previous one.
You must ensure that the commands you send are real telnet commands - telnet expects a \0 byte after \r\n (see the RFC), so certain servers may freak if \0 is not present.
So:
var net = require('net');
var conn = net.createConnection(8888, 'localhost');
conn.on('connect', function() {
console.log(conn.write(command_1) &&
conn.write(command_2) &&
conn.write(command_3) &&
//...
conn.write(command_n))
})
conn.on('data', function () {})
If it writes false - then you must wait for 'drain'. If it writes true - you must implement waiting. I discourage the event-based solution and suggest to look at using async or Step NPM modules instead.

Related

Function returns before its finished

I'm trying to implement a socket connection between a python server and a flutter client,
everything works well, but when I want to get the response back the function returns null and then prints the response.
I'm receiving the response but after the function returns.
String rcev_response() {
String response = "";
socket.listen((event) {
response = utf8.decode(event);
print(response);
});
return response;
}
Any idea what's happening here and how can I fix it?
EDIT:
After a little bit of debugging, I found out that socket.listen() doesn't actually stop. so the function returns the value before its assigned
and I added a 1ms delay before the return and now it's working properly.
Timer(Duration(seconds: 1), onceAtTheEndOfTheBatch);
this is still not a solution. any help would be appreciated.
try to add async
Future<String> rcev_response() async {
String response = "";
await socket.listen((event) {
response = utf8.decode(event);
print(response);
});
return response;}
maybe this help you :)
The anonymous function that you are passing to listen is going to be called multiple times with chunks of the response. It's up to you to concatenate them. As you need a string you can use the stream join convenience function.
Future<String> rcev_response() async {
Socket s = await Socket.connect(ipAddr, port);
s.add(utf8.encode(request));
String result = await utf8.decoder.bind(s).join();
await s.close(); // probably need to close the socket
return result;
}
This assumes that the server will close the socket when it's finished sending.
A solution but still not optimal.
I found out that it works properly if I close the socket from the server side and re-initialize it every time I send a request from the client side.
For example - Server side process:
# accept connection
client_socket, client_address = self.server_socket.accept()
# receive the message
client_socket.recv()
# send response
client_socket.send()
# close socket
client_socket.close()
But I still want to keep the connection alive as a full duplex connection, if anyone can help.

What is the use of boost::asio::async_write function

Can anyone please help me with this code , what is the use of "boost::asio::async_write" function here
Does it sends acknowledgment back to the client ?
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
boost::asio::async_write(socket_,
boost::asio::buffer(data_, bytes_transferred),
boost::bind(&session::handle_write, this,
boost::asio::placeholders::error));
}
else
{
delete this;
}
}
It looks like this is from an "echo server" example. async_write writes the contents of boost::asio::buffer(data_, bytes_transferred) to the socket.
Since we're inside handle_read we can guess that this function itself is the completion handler for a likely async_read call that filled that data_ buffer. Since we use the exact number of bytes reported back by async_read (bytes_transferred) and there's no visible manipulation on data_, we can assume that this simply sends the exact message (or data in general) received to socket_. If socket_ was also the endpoint in the async_read this is the definition of an echo server.

Rust persistent TcpStream

I seem to be struggling with the std::io::TcpStream. I'm actually trying to open a TCP connection with another system but the below code emulates the problem exactly.
I have a Tcp server that simply writes "Hello World" to the TcpStream upon opening and then loops to keep the connection open.
fn main() {
let listener = io::TcpListener::bind("127.0.0.1", 8080);
let mut acceptor = listener.listen();
for stream in acceptor.incoming() {
match stream {
Err(_) => { /* connection failed */ }
Ok(stream) => spawn(proc() {
handle(stream);
})
}
}
drop(acceptor);
}
fn handle(mut stream: io::TcpStream) {
stream.write(b"Hello Connection");
loop {}
}
All the client does is attempt to read a single byte from the connection and print it.
fn main() {
let mut socket = io::TcpStream::connect("127.0.0.1", 8080).unwrap();
loop {
match socket.read_byte() {
Ok(i) => print!("{}", i),
Err(e) => {
println!("Error: {}", e);
break
}
}
}
}
Now the problem is my client remains blocked on the read until I kill the server or close the TCP connection. This is not what I want, I need to open a TCP connection for a very long time and send messages back and forth between client and server. What am I misunderstanding here? I have the exact same problem with the real system i'm communicating with - I only become unblocked once I kill the connection.
Unfortunately, Rust does not have any facility for asynchronous I/O now. There are some attempts to rectify the situation, but they are far from complete yet. That is, there is a desire to make truly asynchronous I/O possible (proposals include selecting over I/O sources and channels at the same time, which would allow waking tasks which are blocked inside an I/O operation via an event over a channel, though it is not clear how this should be implemented on all supported platforms), but there's still a lot to do and there's nothing really usable now, as far as I'm aware.
You can emulate this to some extent with timeouts, however. This is far from the best solution, but it works. It could look like this (simplified example from my code base):
let mut socket = UdpSocket::bind(address).unwrap();
let mut buf = [0u8, ..MAX_BUF_LEN];
loop {
socket.set_read_timeout(Some(5000));
match socket.recv_from(buf) {
Ok((amt, src)) => { /* handle successful read */ }
Err(ref e) if e.kind == TimedOut => {} // continue
Err(e) => fail!("error receiving data: {}", e) // bail out
}
// do other work, check exit flags, for example
}
Here recv_from will return IoError with kind set to TimedOut if there is no data available on the socket during 5 seconds inside recv_from call. You need to reset the timeout before inside each loop iteration since it is more like a "deadline" than a timeout - when it expires, all calls will start to fail with timeout error.
This is definitely not the way it should be done, but Rust currently does not provide anything better. At least it does its work.
Update
There is now an attempt to create an asynchronous event loop and network I/O based on it. It is called mio. It probably can be a good temporary (or even permanent, who knows) solution for asynchronous I/O.

Async sockets in D

Okay this is my first question here on Stack Overflow, so bare over with it if I'm not asking properly.
Basically I'm trying to code some asynchronous sockets using std.socket, but I'm not sure if I've understood the concept correct. I've only ever worked with asynchronous sockets in C# and in D it seem to be on a much lower level. I've researched a lot and looked up a lot of code, documentation etc. both for D and C/C++ to get an understanding, however I'm not sure if I understand the concept correctly and if any of you have some examples. I tried looking at splat, but it's very outdated and vibe seems to be too complex just for a simple asynchronous socket wrapper.
If I understood correctly there is no poll() function in std.socket so you'd have to use SocketSet with a single socket on select() to poll the status of the socket right?
So basically how I'd go about handling the sockets is polling to get the read status of the socket and if it has a success (value > 0) then I can call receive() which will return 0 for disconnection else the received value, but I'd have to keep doing this until the expected bytes are received.
Of course the socket is set to nonblocked!
Is that correct?
Here is the code I've made up so far.
void HANDLE_READ()
{
while (true)
{
synchronized
{
auto events = cast(AsyncObject[int])ASYNC_EVENTS_READ;
foreach (asyncObject; events)
{
int poll = pollRecv(asyncObject.socket.m_socket);
switch (poll)
{
case 0:
{
throw new SocketException("The socket had a time out!");
continue;
}
default:
{
if (poll <= -1)
{
throw new SocketException("The socket was interrupted!");
continue;
}
int recvGetSize = (asyncObject.socket.m_readBuffer.length - asyncObject.socket.readSize);
ubyte[] recvBuffer = new ubyte[recvGetSize];
int recv = asyncObject.socket.m_socket.receive(recvBuffer);
if (recv == 0)
{
removeAsyncObject(asyncObject.event_id, true);
asyncObject.socket.disconnect();
continue;
}
asyncObject.socket.m_readBuffer ~= recvBuffer;
asyncObject.socket.readSize += recv;
if (asyncObject.socket.readSize == asyncObject.socket.expectedReadSize)
{
removeAsyncObject(asyncObject.event_id, true);
asyncObject.event(asyncObject.socket);
}
break;
}
}
}
}
}
}
So basically how I'd go about handling the sockets is polling to get the read status of the socket
Not quite right. Usually, the idea is to build an event loop around select, so that your application is idle as long as there are no network or timer events that need to be handled. With polling, you'd have to check for new events continuously or on a timer, which leads to wasted CPU cycles, and events getting handled a bit later than they occur.
In the event loop, you populate the SocketSets with sockets whose events you are interested in. If you want to be notified of new received data on a socket, it goes to the "readable" set. If you have data to send, the socket should be in the "writable" set. And all sockets should be on the "error" set.
select will then block (sleep) until an event comes in, and fill the SocketSets with the sockets which have actionable events. Your application can then respond to them appropriately: receive data for readable sockets, send queued data for writable sockets, and perform cleanup for errored sockets.
Here's my D implementation of non-fiber event-based networking: ae.net.asockets.

Nodejs streaming

I want to realize a simple client-server connection using Nodejs.
But I've encountered with the following problem.
Consider the code
server.js:
var net = require('net'),
sys = require('sys');
net.createServer(onConnection).listen(8124);
function onConnection(socket) {
socket.setNoDelay(true);
socket.addListener("connect", function () {
sys.puts('client connected: ' + this.remoteAddress);
});
socket.addListener("data", function (data) {
sys.puts("message: \n" + data + "\n - end of msg.");
});
socket.addListener("end", function () {
sys.puts('end of connection');
this.end();
});
}
sys.puts('Server running at 127.0.0.1:8124');
client.js:
var net = require('net'),
sys = require('sys');
var stream = net.createConnection(8124);
stream.addListener("connect", function(){
sys.puts('connected');
stream.write('a');
stream.flush();
stream.write('b');
stream.flush();
});
stream.addListener("data", function(data){
sys.puts("Message: \n" + data + "\n - end of msg.");
});
When I run client.js I sometimes get only one message 'ab' instead of two messages 'a' and 'b'.
Is there some 'right method' to deal with that?
TCP is a stream protocol. Single write on one end of the pipe can result in multiple "reads" on the other end, and the other way around. You have to either explicitly tell the other side how many bytes you are sending by including the length in the message; or provide easily recognizable message delimiters. In any case you need to read in a loop.
use socket.write return value and callback as documented here https://nodejs.org/api/net.html#net_socket_write_data_encoding_callback to know when the data is completly flushed to the kernel . Wait for that to happen and after that call the second write. that way you make sure of the ordering. Regarding the problem of logic separartion of "a" and "b" you might want to design/implement that "protocol yourself, it's not a responsiblity of the (low-level) socket API.
FYI, if you are able to structure to be a line-based text protocol, you can use readline. See:
https://nodejs.org/api/readline.html#example-tiny-cli
https://nodejs.org/api/readline.html#example-read-file-stream-line-by-line