문제
나는 IP-Address Gem을 사용하고 있으며 양식의 Netmask에서 변환 할 수있는 능력이없는 것 같습니다.
255.255.255.0
CIDR 형태로
/24
누구든지 전자를 후자로 빠르게 변환하는 방법이 있습니까?
해결책
빠르고 더러운 방법이 있습니다
require 'ipaddr'
puts IPAddr.new("255.255.255.0").to_i.to_s(2).count("1")
적절한 기능이 있어야합니다. 찾을 수 없었기 때문에 "1"을 계산합니다.
여러 곳에서 기능을 사용하고 원숭이를 끼치는 것을 신경 쓰지 않으면 도움이 될 수 있습니다.
IPAddr.class_eval
def to_cidr
"/" + self.to_i.to_s(2).count("1")
end
end
그럼 당신은 얻습니다
IPAddr.new('255.255.255.0').to_cidr
# => "/24"
다른 팁
참고 문자와 마찬가지로, 검색하는 사람들이 정보에 쉽게 액세스 할 수 있도록 ...
CIDR에서 Netmask 형식으로 변환하는 간단한 방법은 다음과 같습니다.
def cidr_to_netmask(cidr)
IPAddr.new('255.255.255.255').mask(cidr).to_s
end
예를 들어:
cidr_to_netmask(24) #=> "255.255.255.0"
cidr_to_netmask(32) #=> "255.255.255.255"
cidr_to_netmask(16) #=> "255.255.0.0"
cidr_to_netmask(22) #=> "255.255.252.0"
다음은 모든 비용으로 문자열을 피하는보다 수학적 접근법입니다.
def cidr_mask
Integer(32-Math.log2((IPAddr.new(mask,Socket::AF_INET).to_i^0xffffffff)+1))
end
"마스크"는 255.255.255.0과 같은 문자열입니다. "마스크"가 이미 IP 주소의 정수 표현 인 경우 첫 번째 인수를 "마스크"로 변경할 수 있습니다.
예를 들어, 마스크가 "255.255.255.0"인 경우 iPaddr.new (Mask, Socket :: af_inet) .to_i는 0xffffff00이되며 0xffffffff가있는 0xffffffff (255)와 같습니다.
우리는 그것을 256 개의 호스트의 전체 범위로 만들기 위해 1을 추가 한 다음 8의 로그베이스 2를 찾아 8 (호스트 주소에 사용되는 비트)을 찾은 다음 32에서 8 (비트)과 같습니다. 네트워크 주소에 사용).
그런 다음 Math.log2가 플로트를 반환하기 때문에 Integer에 캐스트합니다.
빠르고 더러운 변환 :
"255.255.255.0".split(".").map { |e| e.to_i.to_s(2).rjust(8, "0") }.join.count("1").split(".")
=> 배열에서 마스크를 분할합니다
.map { |e| e.to_i.to_s(2).rjust(8, "0") }
=> 배열의 각 요소에 대해 :
.to_i
=> 정수로 변환합니다
.to_s(2)
=> 정수를 이진으로 변환합니다
.rjust(8, "0")
=> 패딩 추가
=>지도는 동일한 카디널리티로 배열을 반환합니다
.join
=> 배열을 전체 문자열로 변환합니다
.count("1")
=> count "1"문자 => CIDR 마스크 제공
def mask_2_ciddr mask
"/" + mask.split(".").map { |e| e.to_i.to_s(2).rjust(8, "0") }.join.count("1").to_s
end
mask_2_ciddr "255.255.255.0"
=> "/24"
mask_2_ciddr "255.255.255.128"
=> "/25"
IP-Address Gem을 사용할 필요가 없다면 netaddr 보석
require 'netaddr'
def to_cidr_mask(dotted_mask)
NetAddr::CIDR.create('0.0.0.0/'+dotted_mask).netmask
end
to_cidr_mask("255.224.0.0") # => "/11"
require 'ipaddr'
def serialize_ipaddr(address)
mask = address.instance_variable_get(:@mask_addr).to_s(2).count('1')
"#{address}/#{mask}"
end
serialize_ipaddr(IPAddr.new('192.168.0.1/24')) # => "192.168.0.0/24"
이 코드는 iPaddr 인스턴스의 개인 인스턴스 변수 *@mask_addr)에 액세스하여 마스킹을 달성합니다 (주소, serialize_ipaddr로 전달). 이것은 권장되지 않습니다 (인스턴스 변수가 클래스 공개 API의 일부가 아니지만 여기서 문자열을 구문 분석하는 것보다 낫습니다. #Inspect 제 생각에는.
따라서 프로세스는 다음과 같습니다.
- 인스턴스 변수를 가져옵니다 @mask_addr 그것은 netmask를 나타냅니다
- 이진 표현을 얻으십시오
255.255.255.0 -> 4294967040 -> 11111111111111111111111100000000
- CIDR 마스크 (24)를 얻으려면베이스 -2 숫자의 1-s를 계산하십시오.
- 주소 및 마스크로 구성된 문자열을 구성하십시오
편집 : Nathanoliver가 요청한대로 구현에 대한 설명이 추가되었습니다.
iPaddr 보석없이 수행하는 방법은 다음과 같습니다.
(('1'*cidr)+('0'*(32-cidr))).scan(/.{8}/m).map{|e|e.to_i(2)}.join('.')