perlipc - Interactive Client with IO::Socket - why does it fork? - perl

I'm reading the perlipc perldoc and was confused by the section entitled "Interactive Client with IO::Socket". It shows a client program that connects with some server and sends a message, receives a response, sends another message, receives a response, ad infinitum. The author, Tom Christiansen, states that writing the client as a single-process program would be "much harder", and proceeds to show an implementation that forks a child process dedicated to reading STDIN and sending to the server, while the parent process reads from the server and writes to STDOUT.
I understand how this works, but I don't understand why it wouldn't be much simpler (rather than harder) to write it as a single-process program:
while (1) {
read from STDIN
write to server
read from server
write to STDOUT
}
Maybe I'm missing the point, but it seems to me this is a bad example. Would you ever really design an client/server application protocol where the server might suddenly think of something else to say, interjecting characters onto the terminal where the client is in the middle of typing his next query?
UPDATE 1: I understand that the example permits asynchronicity; what I'm puzzled about is why concurrent I/O between a CLI client and a server would ever be desirable (due to the jumbling of input and output of text on the terminal). I can't think of any CLI app - client/server or not - that does that.
UPDATE 2: Oh!! Duh... my solution only works if there's exactly one line sent from the server for every line sent by the client. If the server can send an unknown number of lines in response, I'd have to sit in a "read from server" loop - which would never end, unless my protocol defined some special "end of response" token. By handling the sending and receiving in separate processes, you leave it up to the user at the terminal to detect "end of response".
(I wonder whether it's the client, or the server, that typically generates a command prompt? I'd always assumed it was the client, but now I'm thinking it makes more sense for it to be the server.)

Because the <STDIN> read request can block, doing the same thing in a single process requires more complicated, asynchronous handling of the input/output functions:
while (1) {
if there is data in STDIN
read from stdin
write to server
if there is data from server
read from server
write to STDOUT
}

Related

Bidirectional communication of Unix sockets

I'm trying to create a server that sets up a Unix socket and listens for clients which send/receive data. I've made a small repository to recreate the problem.
The server runs and it can receive data from the clients that connect, but I can't get the server response to be read from the client without an error on the server.
I have commented out the offending code on the client and server. Uncomment both to recreate the problem.
When the code to respond to the client is uncommented, I get this error on the server:
thread '' panicked at 'called Result::unwrap() on an Err value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }', src/main.rs:77:42
MRE Link
Your code calls set_read_timeout to set the timeout on the socket. Its documentation states that on Unix it results in a WouldBlock error in case of timeout, which is precisely what happens to you.
As to why your client times out, the likely reason is that the server calls stream.read_to_string(&mut response), which reads the stream until end-of-file. On the other hand, your client calls write_all() followed by flush(), and (after uncommenting the offending code) attempts to read the response. But the attempt to read the response means that the stream is not closed, so the server will wait for EOF, and you have a deadlock on your hands. Note that none of this is specific to Rust; you would have the exact same issue in C++ or Python.
To fix the issue, you need to use a protocol in your communication. A very simple protocol could consist of first sending the message size (in a fixed format, perhaps 4 bytes in length) and only then the actual message. The code that reads from the stream would do the same: first read the message size and then the message itself. Even better than inventing your own protocol would be to use an existing one, e.g. to exchange messages using serde.

How to produce a response body with asynchronously created body chunks in Swift Vapor

I am looking into the Swift Vapor framework.
I am trying to create a controller class that maps data obtained on an SSL link to a third party system (an Asterisk PBX server..) into a response body that is sent over some time down to the client.
So I need to send received text lines (obtained separately on the SSL connection) as they get in, without waiting for a 'complete response' to be constructed.
Seeing this example:
return Response(status: .ok) { chunker in
for name in ["joe\n", "pam\n", "cheryl\n"] {
sleep(1)
try chunker.send(name)
}
try chunker.close()
}
I thought it might be the way to go.
But what I see connecting to the Vapor server is that the REST call waits for the loop to complete, before the three lines are received as result.
How can I obtain to have try chunker.send(name) send it's characters back the client without first waiting for the loop to complete?
In the real code the controller method can potentially keep an HTTP connection to the client open for a long time, sending Asterisk activity data to the client as soon as it is obtained. So each .send(name) should actually pass immediately data to the client, not waiting for the final .close() call.
Adding a try chunker.flush() did not produce any better result..
HTTP requests aren't really designed to work like that. Different browsers and clients will function differently depending on their implementations.
For instance, if you connect with telnet to the chunker example you pasted, you will see the data is sent every second. But Safari on the other hand will wait for the entire response before displaying.
If you want to send chunked data like this reliably, you should use a protocol like WebSockets that is designed for it.

How to implement Socket.PollAsync in C#

Is it possible to implement the equivalent of Socket.Poll in async/await paradigm (or BeginXXX/EndXXX async pattern)?
A method which would act like NetworkStream.ReadAsync or Socket.BeginReceive but:
leave the data in the socket buffer
complete after the specified interval of time if no data arrived (leaving the socket in connected state so that the polling operation can be retried)
I need to implement IMAP IDLE so that the client connects to the mail server and then goes into waiting state where it received data from the server. If the server does not send anything within 10 minutes, the code sends ping to the server (without reconnecting, the connection is never closed), and starts waiting for data again.
In my tests, leaving the data in the buffer seems to be possible if I tell Socket.BeginReceive method to read no more than 0 bytes, e.g.:
sock.BeginReceive(b, 0, 0, SocketFlags.None, null, null)
However, not sure if it indeed will work in all cases, maybe I'm missing something. For instance, if the remote server closes the connection, it may send a zero-byte packet and not sure if Socket.BeginReceive will act identically to Socket.Poll in this case or not.
And the main problem is how to stop socket.BeginReceive without closing the socket.

syslog-ng with unix-stream destination

I am trying to configure syslog-ng destination path to use unix-stream sockets for Inter process communication. I have gone throgh this documentation http://www.balabit.com/sites/default/files/documents/syslog-ng-ose-3.3-guides/en/syslog-ng-ose-v3.3-guide-admin-en/html/configuring_destinations_unixstream.html .
My syslog.conf(only part of it) for the same is as follows:
source s_dxtcp { tcp(ip(0.0.0.0) port(514)); };
filter f_request {program("dxall");};
destination d_dxall_unixstream {unix-stream("/var/run/logs/all.log");};
log {source(s_dxtcp); filter(f_request); destination(d_dxall_unixstream);};
When I restart my syslog-ng server, I have got the following message:
Connection failed; fd='11', server='AF_UNIX(/var/run/logs/all.log)',
local='AF_UNIX(anonymous)', error='Connection refused (111)'
Initiating connection failed, reconnecting; time_reopen='60'
What this error signifies? How can I use unix sockets with syslog-ng? Could any one help me out.
Till now I am not able to create a Unix Domain Socket for inter process communication. But I got a way around it. All I want is a one way communication to send data created at syslog-ng to a running java program(a process, I can say). This I achieved with Using Named Pipes in Syslog-ng. Documents for achieving is http://www.balabit.com/sites/default/files/documents/syslog-ng-ose-3.4-guides/en/syslog-ng-ose-v3.4-guide-admin/html-single/index.html#configuring-destinations-pipe .
Reading from Named Pipe is same as reading from a normal file. One important point to note is that Reader process(here the Java program) should be started before Syslog-ng, (Writer, that writes log messages to the Named pipe).
Reason, Writer will block until there is a Reader. Absence of Reader will lead to loss of some messages, that got accumulated before Reader Started. And there should be only one instance of Reader. If there are multiple readers, the second reader will get null pointer exception, as the message it want to read is already read by the first Reader. Kindly note that this is from my experience. Let me know, If I am wrong.

Is there a mod_perl2/Perl 5 equivalent to PHP's ignore_user_abort()?

I'm writing an internal service that needs to touch a mod_perl2 instance for a long-running-process. The job is fired from a HTTP POST, and them mod_perl handler picks it up and does the work. It could take a long time, and is ready to be handled asynchronously, so I was hoping I could terminate the HTTP connection while it is running.
PHP has a function ignore_user_abort(), that when combined with the right headers, can close the HTTP connection early, while leaving the process running (this technique is mentioned here on SO a few times).
Does Perl have an equivalent? I haven't been able to find one yet.
Ok, I figured it out.
Mod_perl has the 'opposite' problem of PHP here. By default, mod_perl processes are left open, even if the connection is aborted, where PHP by default closes the process.
The Practical mod_perl book says how to deal with aborted connections.
(BTW, for the purposes of this specific problem, a job queue was lower on the list than a 'disconnecting' http process)
#setup headers
$r->content_type('text/html');
$s = some_sub_returns_string();
$r->connection->keepalive(Apache2::Const::CONN_CLOSE);
$r->headers_out()->{'Content-Length'} = length($s);
$r->print($s);
$r->rflush();
#
# !!! at this point, the connection will close to the client
#
#do long running stuff
do_long_running_sub();
You may want to look at using a job queue for this. Here is one provided by Zend that will let you start background processing jobs. There should be a number of these to choose from for php and perl.
Here's another thread that talks about this problem and an article on some php options. I'm not perl monk, so I'll leave suggestions on those tools to others.