Skip to content

Instantly share code, notes, and snippets.

@mrThe
Created January 23, 2017 10:11
Show Gist options
  • Save mrThe/14f44580e7c1e4f44692bf293a816efd to your computer and use it in GitHub Desktop.
Save mrThe/14f44580e7c1e4f44692bf293a816efd to your computer and use it in GitHub Desktop.
Ruby #port_open?
def port_open?(host, port, timeout = 5)
addr = Socket.getaddrinfo(host, nil)
sockaddr = Socket.pack_sockaddr_in(port, addr[0][3])
Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0).tap do |socket|
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
begin
# Initiate the socket connection in the background. If it doesn't fail
# immediatelyit will raise an IO::WaitWritable (Errno::EINPROGRESS)
# indicating the connection is in progress.
socket.connect_nonblock(sockaddr)
rescue IO::WaitWritable
# IO.select will block until the socket is writable or the timeout
# is exceeded - whichever comes first.
if IO.select(nil, [socket], nil, timeout)
begin
# Verify there is now a good connection
socket.connect_nonblock(sockaddr)
rescue Errno::ECONNRESET
# coz fuck this, i don't care
return false
rescue Errno::ECONNREFUSED
# coz fuck this, i don't care
return false
rescue Errno::EISCONN
# Good news everybody, the socket is connected!
rescue
# An unexpected exception was raised - the connection is no good.
socket.close
raise
end
else
# IO.select returns nil when the socket is not ready before timeout
# seconds have elapsed
socket.close
return false
end
end
end
true
end
# usage
begin
port_open?('google.com', 80)
rescue Errno::ENETUNREACH, Errno::ECONNREFUSED
false
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment