struct Socket::IPAddress

Overview

IP address representation.

Holds a binary representation of an IP address, either translated from a String, or directly received from an opened connection (e.g. Socket#local_address, Socket#receive).

IPAddress won't resolve domains, including localhost. If you must resolve an IP, or don't know whether a String contains an IP or a domain name, you should use Addrinfo.resolve instead.

Defined in:

socket/address.cr

Constant Summary

BROADCAST = "255.255.255.255"
BROADCAST6 = "ff0X::1"
LOOPBACK = "127.0.0.1"
LOOPBACK6 = "::1"
UNSPECIFIED = "0.0.0.0"
UNSPECIFIED6 = "::"

Constructors

Class Method Summary

Instance Method Summary

Instance methods inherited from struct Socket::Address

family : Family family, size : Int32 size, to_unsafe : Pointer(LibC::Sockaddr) to_unsafe

Constructor methods inherited from struct Socket::Address

from(sockaddr : Pointer(LibC::Sockaddr), addrlen) : Address
from(sockaddr : Pointer(LibC::Sockaddr)) : Address
from
, new(family : Family, size : Int32) new, parse(uri : URI) : self
parse(uri : String) : self
parse

Instance methods inherited from struct Struct

==(other) : Bool ==, hash(hasher) hash, inspect(io : IO) : Nil inspect, pretty_print(pp) : Nil pretty_print, to_s(io : IO) : Nil to_s

Instance methods inherited from struct Value

==(other : JSON::Any)
==(other : YAML::Any)
==(other)
==
, dup dup

Instance methods inherited from class Object

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other)
===
, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash
hash
, in?(collection : Object) : Bool
in?(*values : Object) : Bool
in?
, inspect(io : IO) : Nil
inspect : String
inspect
, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil!
not_nil!
, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String
to_json
, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil
to_pretty_json
, to_s(io : IO) : Nil
to_s : String
to_s
, to_yaml(io : IO) : Nil
to_yaml : String
to_yaml
, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

Class methods inherited from class Object

from_json(string_or_io, root : String)
from_json(string_or_io)
from_json
, from_yaml(string_or_io : String | IO) from_yaml

Macros inherited from class Object

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

Constructor Detail

def self.from(sockaddr : Pointer(LibC::Sockaddr), addrlen) : IPAddress #

Creates an IPAddress from the internal OS representation. Supports both INET and INET6 families.


[View source]
def self.from(sockaddr : Pointer(LibC::Sockaddr)) : IPAddress #

Creates an IPAddress from the internal OS representation. Supports both INET and INET6 families.


[View source]
def self.new(address : String, port : Int32) #

Creates an IPAddress from the given IPv4 or IPv6 address and port number.

address is parsed using .parse_v4_fields? and .parse_v6_fields?. Raises Socket::Error if address does not contain a valid IP address or the port number is out of range.

Scoped/Zoned IPv6 link-local addresses are supported per RFC4007, e.g. fe80::abcd%eth0 but will always use their numerical interface index in the #inspect representation. The interface name can be retrieved later using #link_local_interface on the IPAddress object.

require "socket"

Socket::IPAddress.new("127.0.0.1", 8080)                 # => Socket::IPAddress(127.0.0.1:8080)
Socket::IPAddress.new("fe80::2ab2:bdff:fe59:8e2c", 1234) # => Socket::IPAddress([fe80::2ab2:bdff:fe59:8e2c]:1234)
Socket::IPAddress.new("fe80::4567:8:9%eth0", 443)        # => Socket::IPAddress([fe80::4567:8:9%2]:443)

[View source]
def self.parse(uri : URI) : IPAddress #

Parses a Socket::IPAddress from an URI.

It expects the URI to include <scheme>://<host>:<port> where scheme as well as any additional URI components (such as path or query) are ignored.

host must be an IP address (v4 or v6), otherwise Socket::Error will be raised. Domain names will not be resolved.

require "socket"

Socket::IPAddress.parse("tcp://127.0.0.1:8080") # => Socket::IPAddress.new("127.0.0.1", 8080)
Socket::IPAddress.parse("udp://[::1]:8080")     # => Socket::IPAddress.new("::1", 8080)

[View source]
def self.parse(uri : String) : self #

Parses a Socket::IPAddress from an URI.

It expects the URI to include <scheme>://<host>:<port> where scheme as well as any additional URI components (such as path or query) are ignored.

host must be an IP address (v4 or v6), otherwise Socket::Error will be raised. Domain names will not be resolved.

require "socket"

Socket::IPAddress.parse("tcp://127.0.0.1:8080") # => Socket::IPAddress.new("127.0.0.1", 8080)
Socket::IPAddress.parse("udp://[::1]:8080")     # => Socket::IPAddress.new("::1", 8080)

[View source]
def self.v4(x0 : Int, x1 : Int, x2 : Int, x3 : Int, *, port : Int) : self #

Returns the IPv4 address x0.x1.x2.x3:port.

Raises Socket::Error if any field or the port number is out of range.


[View source]
def self.v4(fields : StaticArray(UInt8, 4), port : UInt16) : self #

Returns the IPv4 address with the given address fields and port number.


[View source]
def self.v4_mapped_v6(x0 : Int, x1 : Int, x2 : Int, x3 : Int, *, port : Int) : self #

Returns the IPv4-mapped IPv6 address [::ffff:x0.x1.x2.x3]:port.

Raises Socket::Error if any field or the port number is out of range.


[View source]
def self.v4_mapped_v6(fields : StaticArray(UInt8, 4), port : UInt16) : self #

Returns the IPv4-mapped IPv6 address with the given IPv4 address fields and port number.


[View source]
def self.v6(x0 : Int, x1 : Int, x2 : Int, x3 : Int, x4 : Int, x5 : Int, x6 : Int, x7 : Int, *, port : Int, zone_id : Int32 = 0) : self #

Returns the IPv6 address [x0:x1:x2:x3:x4:x5:x6:x7]:port.

Raises Socket::Error if any field or the port number is out of range.


[View source]
def self.v6(fields : StaticArray(UInt16, 8), port : UInt16, zone_id : Int32 = 0) : self #

Returns the IPv6 address with the given address fields, port number and scope identifier.


[View source]

Class Method Detail

def self.parse_v4_fields?(str : String) : StaticArray(UInt8, 4) | Nil #

Parses str as an IPv4 address and returns its fields, or returns nil if str does not contain a valid IPv4 address.

The format of IPv4 addresses follows RFC 3493, section 6.3. No extensions (e.g. octal fields, fewer than 4 fields) are supported.

require "socket"

Socket::IPAddress.parse_v4_fields?("192.168.0.1")     # => UInt8.static_array(192, 168, 0, 1)
Socket::IPAddress.parse_v4_fields?("255.255.255.254") # => UInt8.static_array(255, 255, 255, 254)
Socket::IPAddress.parse_v4_fields?("01.2.3.4")        # => nil

[View source]
def self.parse_v6_fields?(str : String) : StaticArray(UInt16, 8) | Nil #

Parses str as an IPv6 address and returns its fields, or returns nil if str does not contain a valid IPv6 address.

The format of IPv6 addresses follows RFC 4291, section 2.2. Both canonical and non-canonical forms are supported.

require "socket"

Socket::IPAddress.parse_v6_fields?("::1")                 # => UInt16.static_array(0, 0, 0, 0, 0, 0, 0, 1)
Socket::IPAddress.parse_v6_fields?("a:0b:00c:000d:E:F::") # => UInt16.static_array(10, 11, 12, 13, 14, 15, 0, 0)
Socket::IPAddress.parse_v6_fields?("::ffff:192.168.1.1")  # => UInt16.static_array(0, 0, 0, 0, 0, 0xffff, 0xc0a8, 0x0101)
Socket::IPAddress.parse_v6_fields?("1::2::")              # => nil
Socket::IPAddress.parse_v6_fields?("fe80::a:b%eth0")      # => StaticArray[65152, 0, 0, 0, 0, 0, 10, 11]

[View source]
def self.valid?(address : String) : Bool #

Returns true if address is a valid IPv4 or IPv6 address.


[View source]
def self.valid_port?(port : Int) : Bool #

Returns true if port is a valid port number.

Valid port numbers are in the range 0..65_535.


[View source]
def self.valid_v4?(address : String) : Bool #

Returns true if address is a valid IPv4 address.


[View source]
def self.valid_v6?(address : String) : Bool #

Returns true if address is a valid IPv6 address.


[View source]

Instance Method Detail

def ==(other : self) #

def address : String #

Returns a String representation of the IP address, without the port number.

IPv6 addresses are canonicalized according to RFC 5952, section 4. IPv4-mapped IPv6 addresses use the mixed notation according to RFC 5952, section 5.

require "socket"

v4 = Socket::IPAddress.v4(UInt8.static_array(127, 0, 0, 1), 8080)
v4.address # => "127.0.0.1"

v6 = Socket::IPAddress.v6(UInt16.static_array(0x2001, 0xdb8, 0, 0, 1, 0, 0, 1), 443)
v6.address # => "2001:db8::1:0:0:1"

mapped = Socket::IPAddress.v4_mapped_v6(UInt8.static_array(192, 168, 1, 15), 55001)
mapped.address # => "::ffff:192.168.1.15"

To obtain both the address and the port number in one string, see #to_s.


[View source]
def hash(hasher) #
Description copied from struct Struct

See Object#hash(hasher)


def inspect(io : IO) : Nil #
Description copied from struct Struct

Appends this struct's name and instance variables names and values to the given IO.

struct Point
  def initialize(@x : Int32, @y : Int32)
  end
end

p1 = Point.new 1, 2
p1.to_s    # "Point(@x=1, @y=2)"
p1.inspect # "Point(@x=1, @y=2)"

[View source]
def inspect : String #
Description copied from class Object

Returns an unambiguous and information-rich string representation of this object, typically intended for developers.

This method should usually not be overridden. It delegates to #inspect(IO) which can be overridden for custom implementations.

Also see #to_s.


[View source]
def link_local? #

Returns true if this IP is a link-local address.

IPv4 addresses in 169.254.0.0/16 reserved by RFC 3927 and Link-Local IPv6 Unicast Addresses in fe80::/10 reserved by RFC 4291 are considered link-local.


[View source]
def link_local_interface : String | Nil #

Returns the interface name for a scoped/zoned link-local IPv6 address. This only works on properly initialized link-local IPv6 address objects. In any other case this will return nil.

The OS tracks the zone via a numerical interface index as enumerated by the kernel. To keep our abstraction class in line, we also only keep the interface index around.

This helper method exists to look up the interface name based on the associated zone_id property.


[View source]
def loopback? : Bool #

Returns true if this IP is a loopback address.

In the IPv4 family, loopback addresses are all addresses in the subnet 127.0.0.0/24. In IPv6 ::1 is the loopback address.


[View source]
def port : Int32 #

[View source]
def pretty_print(pp) #

[View source]
def private? : Bool #

Returns true if this IP is a private address.

IPv4 addresses in 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16 as defined in RFC 1918 and IPv6 Unique Local Addresses in fc00::/7 as defined in RFC 4193 are considered private.


[View source]
def to_s(io : IO) : Nil #

Writes the String representation of the IP address plus the port number to the given io.

IPv6 addresses are canonicalized according to RFC 5952, section 4, and surrounded within a pair of square brackets according to RFC 3986. IPv4-mapped IPv6 addresses use the mixed notation according to RFC 5952, section 5.

To obtain the address alone without the port number, see #address.


[View source]
def to_s : String #

Returns a String representation of the IP address plus the port number.

IPv6 addresses are canonicalized according to RFC 5952, section 4, and surrounded within a pair of square brackets according to RFC 3986. IPv4-mapped IPv6 addresses use the mixed notation according to RFC 5952, section 5.

require "socket"

v4 = Socket::IPAddress.v4(UInt8.static_array(127, 0, 0, 1), 8080)
v4.to_s # => "127.0.0.1:8080"

v6 = Socket::IPAddress.v6(UInt16.static_array(0x2001, 0xdb8, 0, 0, 1, 0, 0, 1), 443)
v6.to_s # => "[2001:db8::1:0:0:1]:443"

mapped = Socket::IPAddress.v4_mapped_v6(UInt8.static_array(192, 168, 1, 15), 55001)
mapped.to_s # => "[::ffff:192.168.1.15]:55001"

To obtain the address alone without the port number, see #address.


[View source]
def to_unsafe : Pointer(LibC::Sockaddr) #

[View source]
def unspecified? : Bool #

Returns true if this IP is an unspecified address, either the IPv4 address 0.0.0.0 or the IPv6 address ::.


[View source]
def zone_id : Int32 #

[View source]