Как преобразовать IP-адрес в IP-номер в Haskell?

#haskell #ip

#haskell #ip

Вопрос:

Какой самый простой способ взять строку, содержащую адрес IPv4 или IPv6, и получить IP-номер?

Комментарии:

1. IP … номер? Что именно вы ищете? A data IP4 = IP4 Word8 Word8 Word8 Word8 или что-то для библиотек C?

2. Например, «134.244.11.55» и получить 2264140599, мне также нужно сделать это для IPv6.

3. Итак, вам нужно 32-битное целое число для IPv4 и 128-битное целое число для IPv6? Или, я думаю, просто Integer , я не думаю, что 128-битные целые числа с фиксированной шириной находятся в стандартной библиотеке.

Ответ №1:

Вот готовое к копированию решение:

 module Program where

import Data.IP

ipToOcts :: IP -> [Int]
ipToOcts (IPv4 ip) = fromIPv4 ip
ipToOcts (IPv6 ip) = fromIPv6b ip

ipToInteger :: IP -> Integer
ipToInteger =
    sum . map ((n,o) -> toInteger o * 256 ^ n) . zip [0..] . reverse . ipToOcts

ipStringToInteger :: String -> Integer
ipStringToInteger = ipToInteger . read
  

Примеры вызовов:

 ipStringToInteger "134.244.11.55"
ipStringToInteger "2001:db8:00:00:00:00:00:01"
  

Для этого вам нужен пакет iproute:

 cabal install iproute
  

Ответ №2:

Data.IP имеет IPv4 и IPv6 типы, которые поддерживают синтаксический анализ из строк, а также функции для преобразования их в списки Int значений.

 > fromIPv4 . read "192.0.0.1"
[192,0,0,1]
> fromIPv6b . read "2001:0db8::1"
[32,1,13,184,0,0,0,0,0,0,0,0,0,0,0,1]
  

Как только у вас будет список, вы можете свернуть его до одного целого числа, если хотите:

 > import Data.List
> foldl' (acc octet -> 256*acc   fromIntegral octet) 0 [192,0,0,1]
3221225473
  

(Поскольку оба fromIPv4 и fromIPv6 возвращают [Int] значения, fromIntegeral гарантирует, что fold может возвращать an Integer .)

Однако подумайте, действительно ли вам нужно одно целое число. Любой API, который у вас есть, действительно будет связан с отдельными байтами в правильном порядке. Кроме сериализации адреса в двоичный файл, вам, вероятно, это даже не нужно.

Ответ №3:

в 2018 году был выпущен ip-пакет, который очень удобен для этой цели.

Расшифровать

 λ> import Net.IP
λ> :set -XOverloadedStrings
λ> decode "127.0.0.1"
Just (ipv4 127 0 0 1)
λ> decode "2a02:2450:dd1f:0:7646:a0ff:fe91:67b1"
Just (ipv6 0x2a02 0x2450 0xdd1f 0x0000 0x7646 0xa0ff 0xfe91 0x67b1)
  

Кодировать

 λ> encode (ipv4 127 0 0 1)
"127.0.0.1"
λ> encode (ipv6 0x2a02 0x2450 0xdd1f 0x0000 0x7646 0xa0ff 0xfe91 0x67b1)
"2a02:2450:dd1f::7646:a0ff:fe91:67b1
  

Пакет обеспечивает интеграцию Attoparsec.