17 Mart 2016 Perşembe

IP-String Adres Dönüşüm Metodları

Not:
Bazen DNS sunucusunu kullanarak sorgulama yapmak gerekir. Konuyla ilgili DNS Metodları başlıklı yazıya bakabilirsiniz.

Giriş
Adres dönüşüm metodları, DNS sunucusuna istek göndermeden yapılabilen basit hesaplamalar. Noktalı IP adreslerini 4 byte'a veya 4 byte'tan tekrar noktalı gösterime çevirmeye yararlar. Socket programlamada bu konu illaki karşımıza çıkar. Java da InetAddress sınıfı ile bu tür dönüşümleri yapmaya gerek kalmıyor. En fazla kullanmamız gerek kod aşağıdakine benziyor.
InetAddress addr = InetAddress.getByName("127.0.0.1");

C dilinde ise bir çok metodu ve farkını bilmek gerekiyor. Bu yüzden bu yazıyı yazdım.

1. Metin IP Adresini Long'a Çevirme
inet_xxx ile başlayan metodlar "Internet Address Manipulation Routines" cümlesini ima ederler.

inet_pton - En yeni ve kullanmamız gereken POSIX API'si
inet_pton metodu yazısına taşıdım.

inet_aton - deprecated. Use inet_pton
inet_aton metodu yazısına taşıdım.

inet_addr - deprecated. Use inet_pton
inet_aton ile aynıdır. Hatta aralarında ne fark var bilmiyorum. Verilen IP metnini network byte order'ta bir 32 bitlik sayıya çevirir. Metodun içi şuna benzer:
unsigned int inet_addr(char *str)
{
    int a, b, c, d;
    char arr[4];
    sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d);
    arr[0] = a; arr[1] = b; arr[2] = c; arr[3] = d;
    return *(unsigned int *)arr;
}

//use it as follows:
//inet_addr() returns address in Network Byte Order, so no need of htonl()

thesockaddr_in.sin_addr.s_addr = inet_addr(str);
Aynı işlemi C#'ta şöyle yapardık

String ipString = "192.168.0.1";
String[] ipBytes = ipString.Split('.');

uint byte1 = Convert.ToUInt32(ipBytes[0]);
uint byte2 = Convert.ToUInt32(ipBytes[1]);
uint byte3 = Convert.ToUInt32(ipBytes[2]);
uint byte4 = Convert.ToUInt32(ipBytes[3]);

uint IP =   (byte1 << 24) 
            | (byte2 << 16) 
            | (byte3 <<  8) 
            |  byte4 ;

Örnek'te socketi connect işlemine tabi tutmak için doldurulan sockaddr görülebilir:

struct sockaddr_in  sin;
memset(&sin,0,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_port=htons(1234);
if((sin.sin_addr.s_addr = inet_addr(g_szIp)) == INADDR_NONE)
{
//Error 
}


2. Long'u Metin IP adresine çevirme

inet_ntoa - deprecated. use inet_ntop
Bu metod IPv4 için çalışır. Verilen binary IP adresini "192.168.1.2" örneğindeki gibi metne çevirir. İmzası
char *inet_ntoa(struct in_addr in); 
şeklindedir.

inet_ntop
İmzası şöyledir.
const char * inet_ntop(int af, const void *src, char *dst, size_t size)
IPV4 için verilen 4 byte değeri string'e çevirir. Örnek:
// IPv4 demo of inet_ntop() and inet_pton()

struct sockaddr_in sa;
char str[INET_ADDRSTRLEN];

// store this IP address in sa:
inet_pton(AF_INET, "192.0.2.33", &(sa.sin_addr));

// now get it back and print it
inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN);

printf("%s\n", str); // prints "192.0.2.33"
IPv6 için verilen 16 byte değeri string'e çevirir.Bir code golf yarışmasında dünyadaki tüm IPv6 adresleri göstermek için şöyle bir kod kullanılmış. inet_ntop()' geçilen 10 değeri aslında AF_INET6 anlamına geliyor.
__uint128_t i;main(){char s[50];for(;inet_ntop(10,&i,s,49),puts(s),++i>0;);}

İki Long Arasındaki Fark Kaç Tane IP Olduğunu Bulmaya Yarar
Örnek:
IP addresses are a 32 bit integer which we typically express as four octets for human purposes. You could get the number of addresses in a range by turning both into their 32 bit integer representations and subtracting.



5 yorum:

  1. Hocam merhaba.
    IP adresinden yeni bir tekil string oluşturmaya çalışıyorum.
    Yapmaya çalıştığım şey şu:
    1- Kullanıcının IP adresini bul.
    2- Ona herhangi bir yöntem uygula, inet_pton ya da ip2long gibi bir şey.
    3- Yazdır.

    Bunu nasıl yapabilirim. Yardımcı olursanız çok sevinirim.
    Teşekkürler.

    YanıtlaSil
    Yanıtlar
    1. Merhaba. Soruyu doğru anladıysam şöyle yapabilirsiniz. Aşağıdaki kodu çalıştırınca (kod yazıda mevcut) remoteaddr.sin_addr değişkeni içinde bir int sayı elde edersiniz. Bu sayısı da string'e çevirip yazdırırsınız. Umarım yardımcı olur.

      sockaddr_in remoteaddr;
      const char addr[15] = "127.0.0.1";
      inet_pton(AF_INET, (const char*)&addr, &remoteaddr.sin_addr);

      Sil
    2. Özür dilerim yeterince açık yazmamışım. Öncelikle PHP olarak yapmak istiyorum bu işlemi. 127.0.0.1 gibi bir IP adresinden a45b52c gibi bir string oluşturmaya çalışıyorum.

      Client IP'yi bulmak için kullandığım kod bu:

      $xxip = getenv('HTTP_CLIENT_IP')?:
      getenv('HTTP_X_FORWARDED_FOR')?:
      getenv('HTTP_X_FORWARDED')?:
      getenv('HTTP_FORWARDED_FOR')?:
      getenv('HTTP_FORWARDED')?:
      getenv('REMOTE_ADDR');

      En verimli sonucu bu şekilde alıyorum. Teşekkürler.

      Sil
    3. Eğer elinizde ip adresi string olarak varsa. ip2long ile bunu sayısallaştırabilirsiniz.

      Sil
  2. 2a03:2880:10ff:b::face:b00c bunu nasıl ip adresine çebiricez bende bu çıkıyor

    YanıtlaSil