[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How to set socket option SO_RCVTIMEO

Zakaria

11/30/2006 8:50:00 AM

Hi,

How to set socket option SO_RCVTIMEO in Windows XP?
The C version use somekind struct.

Regards,


-- Zakaria
z4k4ri4@gmail.com Yahoo!: z4k4ri4

9 Answers

Kem Mason

11/13/2008 6:08:00 PM

0

Did you ever find out how to do this? I am looking around, haven't
found any documentation

Zakaria wrote:
> Hi,
>
> How to set socket option SO_RCVTIMEO in Windows XP?
> The C version use somekind struct.
>
> Regards,
>
>
> -- Zakaria
> z4k4ri4@gmail.com Yahoo!: z4k4ri4

--
Posted via http://www.ruby-....

Brian Candler

11/13/2008 9:20:00 PM

0

Zakaria wrote:
> How to set socket option SO_RCVTIMEO in Windows XP?
> The C version use somekind struct.

First, read the option:

irb(main):001:0> require 'socket'
=> true
irb(main):002:0> s = TCPServer.new(1234)
=> #<TCPServer:0xb7d246d4>
irb(main):003:0> s.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO)
=> "\000\000\000\000\000\000\000\000"

So if it's a struct timeval, that's a 32-bit tv_sec followed by a 32-bit
tv_usec. Not clear about the byte order, though, since it's all zero
here.

So let's try native byte ordering, to set a timeout of 1.5 seconds (1
second + 500,000 microseconds):

irb(main):008:0> n = [1, 500_000].pack("I_2")
=> "\001\000\000\000 \241\a\000"
irb(main):009:0> s.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, n
)
=> 0
irb(main):010:0> s.accept
Errno::EAGAIN: Resource temporarily unavailable
from (irb):10:in `accept'
from (irb):10
from :0

Yep, there was a pause of 1.5 seconds before the exception was raised.

Look OK?
--
Posted via http://www.ruby-....

Kem Mason

11/13/2008 9:36:00 PM

0


I tried something like that, and it never timed out -- so after your
post, I tried the following (the server I'm connecting to reads a CRLF
terminated string, and returns a response after X seconds (150 in this
case))

sock = TCPSocket.new('foodlinux', 3232)
=> #<TCPSocket:0x2be080>
opt = [1, 1].pack("I_2")
=> "\001\000\000\000\001\000\000\000"
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, opt)
=> 0
sock.write("150\r\n")
=> 5
puts "read: #{sock.gets}"
....

it never times out -- seems like it should return after 1.000001 seconds
regardless of the byte ordering.

What am I missing here?





Brian Candler wrote:
> Zakaria wrote:
>> How to set socket option SO_RCVTIMEO in Windows XP?
>> The C version use somekind struct.
>
> First, read the option:
>
> irb(main):001:0> require 'socket'
> => true
> irb(main):002:0> s = TCPServer.new(1234)
> => #<TCPServer:0xb7d246d4>
> irb(main):003:0> s.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO)
> => "\000\000\000\000\000\000\000\000"
>
> So if it's a struct timeval, that's a 32-bit tv_sec followed by a 32-bit
> tv_usec. Not clear about the byte order, though, since it's all zero
> here.
>
> So let's try native byte ordering, to set a timeout of 1.5 seconds (1
> second + 500,000 microseconds):
>
> irb(main):008:0> n = [1, 500_000].pack("I_2")
> => "\001\000\000\000 \241\a\000"
> irb(main):009:0> s.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, n
> )
> => 0
> irb(main):010:0> s.accept
> Errno::EAGAIN: Resource temporarily unavailable
> from (irb):10:in `accept'
> from (irb):10
> from :0
>
> Yep, there was a pause of 1.5 seconds before the exception was raised.
>
> Look OK?

--
Posted via http://www.ruby-....

Kem Mason

11/13/2008 11:30:00 PM

0


It appears that I am supposed to call setsockopt before connecting --
which would explain why your example (which calls setsockopt before
calling accept()) works, and mine, where it is client side, does not. I
have yet to figure out how to create a client socket that I can call
setsockopt on without connecting right away.

I'll post any update
--
Posted via http://www.ruby-....

Patrick Doyle

11/13/2008 11:48:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

How about something like:

s = Socket.new(...)
s.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, ...)
s.connect(...)

--wpd

On Thu, Nov 13, 2008 at 6:29 PM, Kem Mason <bulbous@gmail.com> wrote:

>
> It appears that I am supposed to call setsockopt before connecting --
> which would explain why your example (which calls setsockopt before
> calling accept()) works, and mine, where it is client side, does not. I
> have yet to figure out how to create a client socket that I can call
> setsockopt on without connecting right away.
>
> I'll post any update
> --
> Posted via http://www.ruby-....
>
>

Kem Mason

11/13/2008 11:51:00 PM

0

hehe yeh I just realized I could use a regular Socket instead of a TCP
Socket -- it doesn't appear to be the only problem though. here's my
latest code (which still doesn't timeout properly)


require 'socket'

opt = [1, 500_000].pack("I_2")

sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
sockaddr = Socket.pack_sockaddr_in(3232, '192.168.1.10')

sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, opt)
puts "sockopt = #{sock.getsockopt(Socket::SOL_SOCKET,
Socket::SO_RCVTIMEO).inspect}"

sock.connect(sockaddr)

#this tells the server at 192.168.1.10:3232 to wait 10 seconds before
responding, so we should get a timeout on our socket
sock.write("10\r\n")

start_time = Time.now
result = sock.gets
time = Time.now - start_time

puts "read: #{sock.gets} after: #{time} seconds"
#no timeout occured, this read returns after 10 seconds




Patrick Doyle wrote:
> How about something like:
>
> s = Socket.new(...)
> s.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, ...)
> s.connect(...)
>
> --wpd

--
Posted via http://www.ruby-....

Brian Candler

11/14/2008 8:05:00 AM

0

Kem Mason wrote:
> hehe yeh I just realized I could use a regular Socket instead of a TCP
> Socket -- it doesn't appear to be the only problem though. here's my
> latest code (which still doesn't timeout properly)

Well, probably you shouldn't be using setsockopt for this at all. Note
that setting SO_RCVTIMEO just raises an EAGAIN on timeout; I'd expect
that gets would trap that and retry.

Why not simply:

require 'timeout'
result = nil
timeout(1.5) {
result = sock.gets
}
--
Posted via http://www.ruby-....

Brian Candler

11/14/2008 8:08:00 AM

0

Also, if you're not concerned about the possibility of transmission
stopping part way through a response, you can do

if select([sock],nil,nil,1.5)
result = sock.gets
else
puts "I timed out!"
end
--
Posted via http://www.ruby-....

Kem Mason

11/14/2008 4:23:00 PM

0


The problem with using timeout is that it is unsafe: (see
http://tinyurl.... )
I have actually encountered a problem using timeout where my thread hung
forever (10 times in production over the last couple months) -- so this
is why I am starting to do something else.

You're right that gets silently ignores the exception -- turns out that
was the main problem -- if I use sock.recvfrom, I get the exception as I
want -- then I just have to handle the case where I get only part of the
response (and still have time left).

All is working now when using the code at: http://pastie....

thanks much for your help all


Brian Candler wrote:
> Kem Mason wrote:
>> hehe yeh I just realized I could use a regular Socket instead of a TCP
>> Socket -- it doesn't appear to be the only problem though. here's my
>> latest code (which still doesn't timeout properly)
>
> Well, probably you shouldn't be using setsockopt for this at all. Note
> that setting SO_RCVTIMEO just raises an EAGAIN on timeout; I'd expect
> that gets would trap that and retry.
>
> Why not simply:
>
> require 'timeout'
> result = nil
> timeout(1.5) {
> result = sock.gets
> }

--
Posted via http://www.ruby-....