All I'm trying to do is see if a connection can be made or not, in a
specified amount of time. Here's the method I've written, would you
mind telling me how I could improve upon it?
def execute
numtries = 0
while numtries < @retries + 1
puts "Trying to connect"
numtries += 1
timeout(@timeoutval, StandardError) {
socket = TCPSocket.new(@host, @port) rescue false
if socket
socket.close
result = TestResult.new
result.testId = @id
result.status = TestResult::STATUS_SUCCEEDED
return result
end
} rescue StandardError
puts "Unable to connect"
sleep @retryDelay if numtries < @retries + 1
end
result = TestResult.new
result.testId = @id
result.status = TestResult::STATUS_FAILED
result.info = "Unable to connect"
return result
end
On Apr 2, 2005 1:09 PM, Sam Roberts <sroberts / uniserve.com> wrote:
> Quoting pergesu / gmail.com, on Sun, Apr 03, 2005 at 03:33:47AM +0900:
> > > > I don't want to override the protocol's idea of a timeout - I'd like
> > > > some means of specifying a timeout for the connection though. In
>
> Be clear that you ARE overriding the protocols idea of a timeout by
> terminating the connect() before the stack has decided the peer cannot
> be connected.
>
> > In Java:
> >
> > Socket s = new Socket();
> > s.connect(new InetSocketAddress(getHost(), port), timeout);
> >
> > I can specify a timeout value for the connection, as you see above.
>
> True enough, I was looking at the TCPSocket constructors, which don't
> allow this. Note this didn't exist prior to JDK 1.4, its a recent hack,
> true to Java's "everything plus the sink" philosophy it looks like.
>
> http://java.sun.com/features/2002/08/j2se-network.html
>
> I still find your "all the other languages" statement a little over the
> top, JDK1.4 isn't a very large "all".
>
> Overriding the TCP protocol's timeouts in the application is
> questionable practice. I'm not telling you how to write your app, you
> might have good reasons to do this, so do it. I am saying that overeager
> timeouts and retransmissions have been known to cause very hard to find
> and fix bugs when applications that work fine on a local network or
> machine mysteriously start timing out over dialup or WiFi links.
>
> > I don't see a way of doing that with the Ruby classes. I'm new to
> > Ruby, so I really don't know - is there a way to do it?
>
> Yes, as I showed you;
>
> begin
> Timeout.timeout(18) do
> TCPSocket.new(...
> end
> rescue Timeout::Error
> ...
> end
>
> You would wrap this into a nice function if you wanted to do it a lot.
>
> Also, you may find that doing your connects in a seperate thread allows
> you to not fiddle with the timeout, and still avoid your app blocking
> if the network is slow or flaky.
>
> Have fun.
> Sam
>
> >
> > On Apr 2, 2005 11:14 AM, Sam Roberts <sroberts / uniserve.com> wrote:
> > > Quoting pergesu / gmail.com, on Sun, Apr 03, 2005 at 02:03:51AM +0900:
> > > > every other language I've used, I can set a timeout value on the
> > > > socket itself. It doesn't look like that's the case in Ruby. Is
> > >
> > > The C, perl, and Java networking APIS don't support timeouts on TCP
> > > connect(), and the C/BSD sockets API is what most (all?) other languages
> > > use internally.
> > >
> > > Out of curiosity, what are these languages?
> > >
> > > > there a method somewhere in the Socket classe heirarchy that lets me
> > > > specify a timeout?
> > > >
> > > > According to timeout, you can set an Exception that gets thrown when
> > > > it times out. I set that to StandardError, and just handle
> > >
> > > Not sure what you mean. You can make timeout raise errors other than
> > > Timeout::Error, and catch them, but you don't do so in the example you
> > > posted.
> > >
> > > > StandardError at the end. According to the docs, Timeout::Error can't
> > > > be used with rescue because it doesn't inherit from StandardError.
> > >
> > > I assure you that Timeout::Error can be caught by rescue, as I showed, I
> > > do it quite often and it works fine.
> > >
> > > > I'd still like some means of setting a timeout value for a socket
> > > > connection. That's a pretty basic aspect of the protocol, there's no
> > > > reason it shouldn't be in there.
> > >
> > > I see no evidence that user configurable timeouts on connect() are not
> > > part of the TCP protocol.
> > >
> > > Cheers,
> > > Sam
> > >
> > > > On Apr 2, 2005 9:37 AM, Sam Roberts <sroberts / uniserve.com> wrote:
> > > > > Quoting pergesu / gmail.com, on Sat, Apr 02, 2005 at 08:05:15PM +0900:
> > > > > > I'm writing a little method that just tries to open a tcp socket
> > > > > > connection, then closes it off. I'm using timeout to limit the amount
> > > > > > of time it tries to connect (is there a better way?). If it times
> > > > >
> > > > > I have to wonder why you want to override the TCP protocols ideas of a
> > > > > timeout. The protocol designers and implementors have a pretty good idea
> > > > > of what the timeouts should be. If its not fast enough for you, you
> > > > > probably want too much. Doing this will make your code flaky and
> > > > > unreliable when the network isn't as fast as your local network. A good
> > > > > text on network programming should explain this. If you are finding your
> > > > > app is blocked, you can use ruby threads to do connections in the
> > > > > background.
> > > > >
> > > > > That said, you can't catch exceptions like that, try:
> > > > >
> > > > > begin
> > > > > Timeout::timeout(3) do
> > > > > long running op
> > > > > end
> > > > > rescue Timeout::Error
> > > > > p "hi"
> > > > > end
> > > > >
> > > > > Sam
> > > > >
> > > > > > out, I just want to say that the connect failed. Despite catching the
> > > > > > Timeout::Error (I think, anyway), I always get the Exception output.
> > > > > > First, here's the method:
> > > > > >
> > > > > > def execute
> > > > > > status = timeout(@timeoutval) {
> > > > > > socket = TCPSocket.new(@host, @port) rescue false
> > > > > >
> > > > > > socket.close if socket
> > > > > > return socket != false
> > > > > > } rescue Timeout::Error
> > > > > >
> > > > > > return false
> > > > > > end
> > > > > >
> > > > > > And now the output from my unit test:
> > > > > >
> > > > > > Started
> > > > > > /usr/local/lib/ruby/1.8/timeout.rb:42:in `new': execution expired
> > > > > > (Timeout::Error)
> > > > > > from ./PortHostTest.rb:16:in `execute'
> > > > > > from ./PortHostTest.rb:15:in `timeout'
> > > > > > from /usr/local/lib/ruby/1.8/timeout.rb:55:in `timeout'
> > > > > > from ./PortHostTest.rb:15:in `execute'
> > > > > > from ./HostTest.rb:10:in `runTest'
> > > > > > from ../tests/test_HostTest.rb:14:in `test_simple'
> > > > > > from /usr/local/lib/ruby/1.8/test/unit/testcase.rb:70:in `__send__'
> > > > > > from /usr/local/lib/ruby/1.8/test/unit/testcase.rb:70:in `run'
> > > > > > ... 10 levels...
> > > > > > from /usr/local/lib/ruby/1.8/test/unit/autorunner.rb:194:in `run'
> > > > > > from /usr/local/lib/ruby/1.8/test/unit/autorunner.rb:14:in `run'
> > > > > > from /usr/local/lib/ruby/1.8/test/unit.rb:285
> > > > > > from /usr/local/lib/ruby/1.8/test/unit.rb:283
> > > > > >
> > > > >
> > > > >
> > > >
> > >
> > >
> >
>
>