Question: how to do (repeated) bidirectional communication with another process via stdin/stdout?


(Carsten Gronski) #1

Thanks, but flushing won’ t help. Something like this does not work.
the program hangs, when trying the second write.

if (ke != nil)
ke.syswrite(loginCall)
ke.flush()
ke.each("\n") { |line| puts(line) }
# we get until here
# this does not get through
ke.syswrite(sysInfoCall)
ke.flush()
# we never get here – program hangs !!
ke.close_write
ke.each("\n") { |line| puts(line) }
ke.close
end

– Carsten

···

ruby-talk@ruby-lang.org schrieb am 15.06.02 19:59:55: > On 2002.06.16, Carsten Gronski cgronski@web.de wrote:

My problem is, that the standard Ruby IO class seems not to allow this
type of repeated bidirectional communication dialog with another
process. Something like ke = IO.popen(“ke.exe”, “r+”) would give me a
bidirectional communication channel, but unfortunatly it is not
possible to read from the I/O stream until the write end of the I/O
stream is closed.

Remember to flush after writing. Or, set the IO to auto-flush.

– Dossy


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)


FreeMail in der Premiumversion! Mit mehr Speicher, mehr Leistung, mehr
Erlebnis und mehr Pramie. Jetzt unter http://club.web.de/?mc=021105


(Yohanes Santoso) #2

ke = IO.popen(“cat”,“r+”)
loginCall = “blablabla\n” # cat needs \n at the end before it echoes back the line
sysInfoCall = “fofofofo\n”

if (ke != nil)
ke.syswrite(loginCall)

#flush() is not needed if you use syswrite, as #flush only flushes

ruby’s internal buffering and ruby does not perform any buffering

with syswrite and sysread

#ke.flush()

#each("\n") blocks until it finds \n or EOF.

#ke.each("\n") { |line| puts(line) }

if you don’t know the number of lines to be read, then you have to use

IO#select so your program does not block unnecessarily.

alternatively if you now the number of lines to be read, just invoke

#readline that many times.

puts ke.readline

ke.syswrite(sysInfoCall)
#ke.flush() # ditto, syswrite does not require flush

ke.close_write

the #each here works because the condition \n or EOF is true.

ke.each("\n") { |line| puts(line) }

ke.close
end


(Dossy) #3

Thanks, but flushing won’ t help. Something like this does not work.
the program hangs, when trying the second write.

if (ke != nil)
ke.syswrite(loginCall)
ke.flush()
ke.each("\n") { |line| puts(line) }
# we get until here
# this does not get through

Right, because the #each will iterate until the remote side closes
their end. What you need to do is read only as many lines as you
need or expect or read until a certain string is received, or
what have you.

If you’re going to use EOF to signal “end of transmission” then
that’s what you’ll have to use, but then you can’t continue to
send and receive like you want. You need to designate some kind
of EOT (end of transmission) sequence so you can keep the connection
open.

ke.syswrite(sysInfoCall)
ke.flush()
# we never get here -- program hangs !!
ke.close_write
ke.each("\n") { |line| puts(line) }
ke.close

end

– Dossy

···

On 2002.06.16, Carsten Gronski cgronski@web.de wrote:


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)