From: Dylan Lukes on 20 Nov 2009 10:12 The problem in question seems to be that only every OTHER line of terminal input is handled by elsif input == STDIN. Here is the complete code, with some masked stuff Code: require 'socket' require 'protocol.rb' #Settings for the server we're connecting too class AmityClient include AmityPackets def initialize #Bool to check if we've received a Ctrl-C, so we can shut down and clean up nicely. @interrupted = false @hostname = "MASKED" @port = 6002 @username = "amity" @mppass = "MASKED" begin puts "Trying to connect to #{@hostname} on #{@port}" @sock = TCPSocket.new(@hostname, @port) sendLogin(@sock, @username, @mppass) sendChat(@sock, "-- Amity b0.1 connected --") run() rescue IOError puts "-- Socket closed --" rescue puts "Error: #{$!}" end end def run while 1 #Enter Infinite Loop #Trap a Ctrl-C, and turn on interrupted trap("INT") {@interrupted = true} #select input results = select([@sock, STDIN], nil, nil) if results != nil then for input in results[0] if input == @sock then #Socket Input found #Socket stuff here elsif input == STDIN #Standard Input found if gets.chomp! == "!quit" then cleanupAndExit else puts gets.chomp! end end #if end #for end #if if @interrupted puts "\nInterrupted! Cleaning up..." cleanupAndExit end end #while end #def def cleanupAndExit @sock.close sendChat(@sock, "User quit Amity Client") exit end end interrupted = false trap("INT") {interrupted = true} amity = AmityClient.new if interrupted puts "Interrupted" exit end -- Posted via http://www.ruby-forum.com/.
From: Robert Klemme on 20 Nov 2009 11:51 On 11/20/2009 04:12 PM, Dylan Lukes wrote: > The problem in question seems to be that only every OTHER line of > terminal input is handled by elsif input == STDIN. Here is the complete > code, with some masked stuff Think about it for a moment: do you believe that such an obvious error in select could have slipped by all tests? No? OK, I don't either. :-) The bug is with 99% likeliness in your code. You have a bug in your input reading code. Look at how you use gets. Cheers robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/
From: Brian Candler on 20 Nov 2009 12:12 if gets.chomp! == "!quit" then cleanupAndExit else puts gets.chomp! end Note how gets is called twice. Incidentally, a plain gets is *not* the same as STDIN.gets, but is more like ARGF.gets. It makes a difference when someone puts some arguments on the command line. Use STDIN.gets to be safe. -- Posted via http://www.ruby-forum.com/.
From: Aldric Giacomoni on 20 Nov 2009 12:14 Brian Candler wrote: > if gets.chomp! == "!quit" then > cleanupAndExit > else > puts gets.chomp! > end > > Note how gets is called twice. Also, I have a question... results = select([@sock, STDIN], nil, nil) for input in results[0] [...] end #for end #if Instead of doing a for loop - just do "results[0].each", which is more idiomatic. The question is, what does "select" do ? rdocs aren't helpful, and I don't understand that bit of code. -- Posted via http://www.ruby-forum.com/.
From: Brian Candler on 20 Nov 2009 14:21
Aldric Giacomoni wrote: > The question is, what does "select" do ? rdocs aren't helpful, and I > don't understand that bit of code. You're right, "ri Kernel#select" and "ri IO::select" are both extremely poor. But it's essentially the same as the C "select" call, which you can read about using "man 2 select" if you have the right manpages installed (under Ubuntu: sudo apt-get manpages-dev) It checks a number of IO descriptors for readiness for reading, writing or exceptional conditions, and returns when at least one of them is ready or a timeout has expired. select([@sock, STDIN], nil, nil) has no timeout parameter so will wait indefinitely. Only read_fds are specified, so it will return an array containing either @sock or STDIN or both, depending on which of them has data to read. -- Posted via http://www.ruby-forum.com/. |