#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.