Hi, How to set socket option SO_RCVTIMEO in Windows XP? The C version use somekind struct. Regards, -- Zakaria z4k4ri4@gmail.com Yahoo!: z4k4ri4
on 2006-11-30 09:51
on 2008-11-13 19:11
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
on 2008-11-13 22:23
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?
on 2008-11-13 22:39
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?
on 2008-11-14 00:32
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
on 2008-11-14 00:51
How about something like: s = Socket.new(...) s.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, ...) s.connect(...) --wpd
on 2008-11-14 00:53
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
on 2008-11-14 09:07
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 }
on 2008-11-14 09:10
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
on 2008-11-14 17:25
The problem with using timeout is that it is unsafe: (see http://tinyurl.com/5fngha ) 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.org/314914 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 > }
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.