문제

나는 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 제 생각에는.

따라서 프로세스는 다음과 같습니다.

  1. 인스턴스 변수를 가져옵니다 @mask_addr 그것은 netmask를 나타냅니다
  2. 이진 표현을 얻으십시오 255.255.255.0 -> 4294967040 -> 11111111111111111111111100000000
  3. CIDR 마스크 (24)를 얻으려면베이스 -2 숫자의 1-s를 계산하십시오.
  4. 주소 및 마스크로 구성된 문자열을 구성하십시오

편집 : Nathanoliver가 요청한대로 구현에 대한 설명이 추가되었습니다.

iPaddr 보석없이 수행하는 방법은 다음과 같습니다.

(('1'*cidr)+('0'*(32-cidr))).scan(/.{8}/m).map{|e|e.to_i(2)}.join('.')
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top