Reputation: 5069
Trying to create a TCP socket in a non-blocking manner, but it failed. Any idea?
$ ruby nonblock_sock.rb
/home/tom/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/socket.rb:1207:in `__connect_nonblock': Operation now in progress - connect(2) would block (IO::EINPROGRESSWaitWritable)
from /home/tom/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/socket.rb:1207:in `connect_nonblock'
from nonblock_sock.rb:6:in `<main>'
Here is the code snippet
#not working yet,
require 'socket'
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
sockaddr = Socket.pack_sockaddr_in(80, 'localhost')
socket.connect_nonblock(sockaddr);
Upvotes: 0
Views: 1888
Reputation: 13014
Change it to:
require 'socket'
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
sockaddr = Socket.pack_sockaddr_in(80, '127.0.0.1') #this
socket.connect_nonblock(sockaddr)
If I recall correctly, one needs to pass the IP instead of hostname(localhost
) while creating address.
With this, connect_nonblock
should raise EINPROGRESS
where it is connecting in non-blocking manner in background which I think we can check with IO.select
later.
Edit:
IO::EINPROGRESSWaitWritable
is raised as expected. connect_nonblock
leaves the connection establishment process for background and raises it.
You should be handling it like this:
begin
socket.connect_nonblock(sockaddr)
rescue Errno::EINPROGRESS
IO.select(nil, [socket]) #wait for socket to be writable
begin
socket.connect_nonblock(sockaddr)
rescue Errno::EISCONN
#=> This means connection to remote host has established successfully.
socket.write("stuff")
end
end
Upvotes: 2