Home Map Index Search News Archives Links About LF
[Top bar]
[Bottom bar]
Bu makalenin farklı dillerde bulunduğu adresler: English  Castellano  Deutsch  Francais  Nederlands  Russian  Turkce  Arabic  

convert to palmConvert to GutenPalm
or to PalmDoc

[Photo of the Author]
tarafından Angel Lopez

Yazar hakkında:

Angel Bilgisayar Mühendisliği mezunu.Şu anda öğretmen olarak Sun Microsystems'de çalışıyor, Solaris ve ağ yönetimi konularını anlatıyor. Son günlerde yardımcı yazar olarak Internet protokolleri konusunda Ra-Ma ile çalışıyor.Tasarlanması ve Unix sistemlerine uyarlanması üzerine.. İlgi duyduğu konuların başında ağ, güvenlik, sistem/ağ unix programlama ve son zamanlarda Linux çekirdeğini kırmak gibi konular uykularını azaltıyor. ;)


İçerik:

Multicast

Çeviri : Ceyhun Elmas

[Ilustration]

Özet:

Bu yazıda TCP/IP ağları üzerine multicast teknolojilerine giriş yapılıyor. Multicast iletişimlerinin teorisi ve multicast programlama için kullanacağımız Linux API detayları üzerinde duruluyor. Çekirdek fonksiyonlarının bu teknolojiye nasıl uyarlandığı gösteriliyor ve genel anlamda Linux altında multicast desteği gözden geçiriliyor. Yazı bir multicast uygulamasının gösterildiği çok basit bir C soket programıyla bitiyor.



 

Giriş

Ağ üzerinden bir yere erişmek (bir arayüz ile) istediğinizde üç çeşit adres kullanabilirsiniz:



Bilgi dönücü, tek bir birim değilse ve çok fazla broadcast oluşturmak istemiyorsak Multicast addresleri çok kullanışlıdır. Özellikle çoğulortam bileşenlerinin(gerçekzamanlı ses ya da video gibi) yoğun kullanıldığı ağ ortamlarında bu durum sözkonusu olacaktır. Bant genişliğini düşündüğümüzde çoğul ortam verileri için unicast en iyi çözüm olmayacaktır.İstemcilerden herhangi biri yerel subnet dışında olduğu sürece broadcast da bir çözüm olmayacaktır.

 

Multicast Adres

Büyük olasılıkla bildiğiniz gibi , IP adresleri uzayı 3 sınıfta gruplanır. .A, B ve C adres sınıfı.Burada dördüncü sınıf olan (D) multicast adresleri için ayrılır. D sınıfına IPv4 adresleri 224.0.0.0 ve 239.255.255.255 uygundur.

IP adreslerinin en önemli 4 biti 224 ile 239 arasında değerler içeririr. Diğer 28 bit, daha az önemli olan multicast grupları için ayrılır, aşağıda görüldüğü gibi :

[grouped bits]


Ağ düzeyinde IPv4 multicast adresleri üzerinde çalışılan ağ çeşidinin fiziksel adresleri üzerine haritalanmalıdır.Eğer unicast ağ adresleri ile çalışıyorsak,ARP protokolü kullanan birleşik fiziksel adresleri getirmeliyiz. Multicast adreslerinde ARP kullanılamaz. Bu nedenle fiziksel adresler başka bir yolla alınmalıdır. Burada bu haritlama yöntemiyle ilgili bazı RFC dokumanları bulunuyor:

Ethernet ağlarında, en yaygın olanı ethernet adresinin en önemli 24 bitinin 01:00:5E haritalanmasıdır. Sonraki bit 0 'a alınır, ve 23 daha az önemli olan bit multicast IPv4 adresin daha az önemli olan 23 bitiyle kullanılır. Bu işlem aşağıdaki grafikte görülüyor:
[transform to Ethernet]

Örneğin, multicast IPv4 adresleri 224.0.0.5 , 01:00:5E:00:00:05 fiziksel ethernet adresine uyum sağlayacaktır.

Burada bazı multicast IPv4 adresleri bulunuyor:

Ayrılmış multicast adreslerinin büyükce bir miktarı, burada gösterilenlerden ayrıdır. "Assigned Numbers" RFC'nin son sürümde tüm yolgösterimleri bulabilirsiniz.

Aşağıdaki tablo her adres aralığı için kullanılan isimlerle ve kendi birleşik TTL'leri (IP paketindeki canlı zaman sayacı) ile tüm multicast adres uzayını gösteriyor. Multicast IPv4'ün altında , TTL iki anlama geliyor. Okuyucuların büyük olasılıkla bildiği üzere, yanlış yapılandırılmış router tablolarının bulunduğu ağlarda sonsuz döngüleri engellemek için datagram'ların yaşam-zaman'larını kontrol eder. Multicast ile çalışır, üstelik datagram'a TTL değeri tanımlanmasına olanak tanır.i. e., ağdaki yolculuk ne kadar uzak olacaktır...Bu durum datagram kategorisi üzerine tanımlamaya olanak sağlar.

Scope align=CENTER>TTL Adres aralığı<</TD> Açıklama
Node 0   Datagram yerel konağa sınırlıdır. Herhangi bir ağ arayüzüne erişemeyecektir.
Link 1 224.0.0.0 - 224.0.0.255 Datagram gönderici konak subnet'ine sınırlandırılacaktır ve router'ın ötesinde bir işlem yapamayacaktır.
Department < 32 239.255.0.0 - 239.255.255.255 Organizasyonun bir bölümü sınırlandırılmıştır.
Organization < 64 239.192.0.0 - 239.195.255.255 Özel organizasyonlar için sınırlandırılmıştır.
Global < 255 224.0.1.0 - 238.255.255.255 Herhangi bir sınırlama olmayan genel uygulamalar.


 

Multicast çalışıyor

LAN içinde, konak üzerindeki ağ arayüzü hedef durumundaki konağa gitmek için gereksinimi olan tüm paketleri alt katmanlara gönderecektir. Bu paket hedef nerdeyse orada olacaktır.(fiziksel ya da broadcast olabilir). Eğer konak bir multicast gruba üye ise, ağ arayüzü bu gruba hedeflenmiş paketleri tanıyacaktır: tüm bu hedef adresler üye olduğu multicast gruplarla eşleşecektir.

Bu nedenle,eğer fiziksel adresi: 0:C0:F6:A0:4A:B1 ve 224.0.1.10 multicast grubuna üye ise, uygun paketler bir sonraki hedef adresten uygun olanına yönelecektir:

Multicast'in WAN üzerinde çalışması için router'ların multicast desteği olmalıdır. Multicast gruba bağlı konakta işlem koşmaya başladığında ,konak subnet'teki her router'a IGMP (Internet Group Management Protocol) gönderir ve multicast mesajların yerel subnet'te işlemi kabul edenlere gönderdiği bilgisini verir. Router'lar kendileri subnet'te hangi multicast mesajının route edilmesi gerekriğini bilerek diğer multicast router'leri bilgilendirecektir.

Üstelik router'lar 224.0.0.1 grubuna IGMP mesajları gondererek her konak ile ilgli grup bilgisini yanıtlayacaktır. Konak, istemini yaptıktan sonra sayacı kendi değerine alacaktır ve sayaç sıfırlandığında yanıtlayacaktır. Bu tüm konakların aynı zamanda yanıt vermesini dolayısıyla ağ üzerine aşırı yüklemeyi engelleyecektir. Konak yanıtladığında grubun multicast adreslerine mesaj gönderecektir.Grup üyesi tüm diğer konaklar yanıtı görecektir ve kendileri yanıtlamayacaktır, onaylayan bir konak, subnet router'in bu gruba multicast mesaj göndermesine yeterlidir.

Eğer tüm konaklar onayladıysa hiç biri yanıtlamayacaktır ve router bu grupta hiç bir konağın ilgisini çekmediğine karar verecektir ve subnet'e giren uyumlu mesajların routing işlemini sonlandıracaktır. Diğer seçenek IGMPv2 ile uyarlanmış ,konaktan geri gelen sinyal iletişimi 224.0.0.2 grubuna mesaj gönderir.

 

Uygulama Programlama Arayüzü (API)

Bir önceki deneyim ile soket programlamada okuyucu yalnızca beş yeni multicast arama seçeneği bulacaktır. Fonksiyonlar setsockopt() ve getsockopt() tanıtmak ya da bu beş seçeneğin değerlerini okumak için kullanılacaktır.Tablo kendi yönetsel veri çeşitleri ve açıklamalarla multicast için sağlanan değerleri gösteriyor:

IPv4 Seçeneği Veri Çeşidi Açıklama
IP_ADD_MEMBERSHIP struct ip_mreq Multicast gruba üye olma.
IP_DROP_MEMBERSHIP struct ip_mreq Multicast grubundan çekilmek.
IP_MULTICAST_IF struct ip_mreq struct ip_mreq multicast mesajların uyumu için özel arayüzler.
IP_MULTICAST_TTL u_char multicast mesajların uyumu için özel TTL.
IP_MULTICAST_LOOP u_char Aktif olan ya da olmayan tekrarlı multicast mesajları.


The ip_mreq yapısı başlık dosyasında tanımlanır , <linux/in.h> aşağıda gösterildiği gibi:

struct ip_mreq {
   struct in_addr imr_multiaddr; /* Grubun IP multicast adresleri */
   struct in_addr imr_interface; /* Arayüzün yerel IP adresleri */
   };
ve multicast seçenekleri:
#define IP_MULTICAST_IF  32
#define IP_MULTICAST_TTL 33
#define IP_MULTICAST_LOOP 34
#define IP_ADD_MEMBERSHIP 35
#define IP_DROP_MEMBERSHIP 36


 

IP_ADD_MEMBERSHIP

Multicast gruba üyelik olabildiğinde bu seçeneği soket üzerine setsockopt() fonksiyonu ile gönderir. ip_mreq parametresi yapıdır.İlk yapı alanı, imr_multiaddr , üye olmak istediğimiz multicast adresleri içerir. İkinci alan , imr_interface , kullanacağımız arayüzün IPv4 adreslerini içerir.

 

IP_DROP_MEMBERSHIP

Bu seçeneği kullanarak işlem multicast grubundan çıkarılabilir. ip_mreq alan yapısı bir önceki konudakine benzer şekilde kullanılır.

 

IP_MULTICAST_IF

Bu seçenek multicast mesajını gönderecek soket olan ağ arayüzünü belirlemede kullanılır. Arayüz ip_mreq içinde bir önceki konudaki gibi verilecektir.

 

IP_MULTICAST_TTL

Datagramlar ile soket kullanan multicast mesajları için TTL (Time To Live) kullanılır. .Kendi değeri 1'dir ,bu datagram'ın yerel subnet'in ötesine geçmeyeceği anlamına gelir.

 

IP_MULTICAST_LOOP

İşlem multicast grubu için mesaj gönderdiğinde eğer arayüz gruba üye ise alınır. Eğer bu kaynak ağ içerisinde herhangi bir yer ise aynı yolla alınacaktır. Bu seçenek bu davranışın aktif olmasını ya da aktif olmamasını sağlar.

 

Basit bir örnek

Nerede multicast gruba mesaj gönderen bir işlem varsa ve bazı işlemler mesajları yanıtlayan gruba aktarılıyorsa ,bunlar ekranda gösteriliyor.

Bir sonraki kod uyarlaması sunucunun multicast grup 224.0.1.1 'e tüm standart girişleri iletmesi ile ilgili. Görebildiğiniz gibi multicast gruba mesaj göndermek için herhangi özel bir harakete gerek yok. Hedef grup adresleri yeterli.
Loopback and TTL değiştirilebildi, eğer kendi değerleri uygulama için uygun değilse.

 

Sunucu

Standard giriş multicast grup 224.0.1.1 'e gönderiliyor.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>

#define MAXBUF 256
#define PUERTO 5000
#define GRUPO "224.0.1.1"

int main(void) {
  int s;
  struct sockaddr_in srv;
  char buf[MAXBUF];

  bzero(&srv, sizeof(srv));
  srv.sin_family = AF_INET;
  srv.sin_port = htons(PUERTO);
  if (inet_aton(GRUPO, &srv.sin_addr) < 0) {
   perror("inet_aton");
   return 1;
  }
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
   perror("socket");
   return 1;
  }

  while (fgets(buf, MAXBUF, stdin)) {
    if (sendto(s, buf, strlen(buf), 0,
              (struct sockaddr *)&srv, sizeof(srv)) < 0) {
      perror("recvfrom");
    } else {
      fprintf(stdout, "Enviado a %s: %s\n", GRUPO, buf);
    }
  }
}


 

İstemci

Aşağıda sunucu tarafından onaylanan multicast grup bilgisi istemci tarafının kodu görülüyor.Alınan mesajlar standart çıkış üzerinde görünüyor. Bu özellik kodun IP_ADD_MEMBERSHIP seçeneniyle sağlanır. Kalan kod UDP mesajlarını alma gereksinimi olan standart işlemler için.

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>

#define MAXBUF 256
#define PUERTO 5000
#define GRUPO "224.0.1.1"

int main(void) {
  int s, n, r;
  struct sockaddr_in srv, cli;
  struct ip_mreq mreq;
  char buf[MAXBUF];

  bzero(&srv, sizeof(srv));
  srv.sin_family = AF_INET;
  srv.sin_port = htons(PUERTO);
  if (inet_aton(GRUPO, &srv.sin_addr) < 0) {
    perror("inet_aton");
    return 1;
  }

  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("socket");
    return 1;
  }

  if (bind(s, (struct sockaddr *)&srv, sizeof(srv)) < 0) {
    perror("bind");
    return 1;
  }

  if (inet_aton(GRUPO, &mreq.imr_multiaddr) < 0) {
    perror("inet_aton");
    return 1;
  }
  mreq.imr_interface.s_addr = htonl(INADDR_ANY);

  if (setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq))
      < 0) {
    perror("setsockopt");
    return 1;
  }

  n = sizeof(cli);
  while (1) {
    if ((r = recvfrom(s, buf, MAXBUF, 0, (struct sockaddr *)
         &cli, &n)) < 0) {
      perror("recvfrom");
    } else {
      buf[r] = 0;
      fprintf(stdout, "Mensaje desde %s: %s\n",
              inet_ntoa(cli.sin_addr), buf);
    }
  }
}


 

Çekirdek ve Multicast

İşlem multicast gruba bağlanmak istediğinde setsockopt fonksiyonu kullanılarak IP düzeyinde IP_ADD_MEMBERSHIP seçeneğine kurar. Bu fonksiyon için gerçek bir uyarlama /usr/src/linux/net/ipv4/ip_sockglue.c üzerine bulunabilir. Kod fonksiyonla çalıştırılarak bu seçeneğe kurulur ya da IP_DROP_MEMBERSHIP aşağıdaki gibidir:

struct ip_mreqn mreq;

if (optlen < sizeof(struct ip_mreq))
  return -EINVAL;
if (optlen >= sizeof(struct ip_mreqn)) {
  if(copy_from_user(&mreq,optval,sizeof(mreq)))
    return -EFAULT;
} else {
  memset(&mreq, 0, sizeof(mreq));
  if (copy_from_user(&mreq,optval,sizeof(struct ip_mreq)))
    return -EFAULT;
}
if (optname == IP_ADD_MEMBERSHIP)
  return ip_mc_join_group(sk,&mreq);
else
  return ip_mc_leave_group(sk,&mreq);


Kodun en baştaki satırlarında giriş parametreleri denetlenir. ip_mreq yapısı, doğru uzunluğa sahiptir ve büyük olasılıkla bunu kullanıcıdan çekirdek alanına kopyalar. Öncelikle parameternin değerini alırız, ip_mc_join_group() fonksiyonu multicast gruba bağlanmak için çağrılır ya da multicast gruptan çıkmak istiyorsak ip_mc_leave_group() fonksiyonu çağrılır.

Bu fonksiyonlar için kod /usr/src/linux/net/ipv4/igmp.c dosyasında bulunur. Gruba bağlanmayı aşağıdaki kısım sağlar :

int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
{
  int err;
  u32 addr = imr->imr_multiaddr.s_addr;
  struct ip_mc_socklist, *iml, *i;
  struct in_device *in_dev;
  int count = 0;


Denetlemenin en başında, MULTICAST macro'ları kullanılıyor, bu macro'lar multicast adresler için ayrılmış aralıkta değişen adreslerdir. Bu, denetleme için yeterlidir. IP adres üzerindeki en önemli byte 224'e alınır.

  if (!MULTICAST(addr))
    return -EINVAL;

    rtnl_shlock();


Denetlemeden sonra, ağ arayüzü multicast grubu aramak üzere kurulur. Eğer ağadaki bir index tarafından bu olanaklı değilse, IPv6 altında olmalıdır, ip_mc_find_dev() fonksiyonu özel IP adresine birleşecek aygıtı bulmak üzere çağrılır. Bu konuya bu yazıda değineceğiz çünkü IPv4 altında çalışıyoruz. Eğer adres INADDR_ANY ise, çekirdek ağ arayüzünü kendisi bulmalıdır, routing tablosunu okur ve burada tanımlı en iyi arayüzü gruba seçer.

  if (!imr->imr_ifindex)
    in_dev = ip_mc_find_dev(imr);
  else
    in_dev = inetdev_by_index(imr->imr_ifindex);

  if (!in_dev) {
    iml = NULL;
    err = -ENODEV;
    goto done;
  }


Daha sonra ip_mc_socklist yapısı için bellek ayırırız, ve aynı grup adres ve arayüzü karşılaştırılan soketlere birleştirilir. Eğer öncesinde soketlere bir birleştirme olduysa fonksiyondan çıkarız , çünkü grup ve arayüze çift birleştirme yapamıyoruz. Eğer ağ arayüz adresi INADDR_ANY değilse, uygunluk sayacı fonksiyon tamamlanmadan artar.

  iml = (struct ip_mc_socklist *)sock_kmalloc(sk, sizeof(*iml),
    GFP_KERNEL);
  err = -EADDRINUSE;
  for (i=sk->ip_mc_list; i; i=i->next) {
    if (memcmp(&i->multi, imr, sizeof(*imr)) == 0) {
      /* New style additions are reference counted */
      if (imr->imr_address.s_addr == 0) {
        i->count++;
        err = 0;
      }
      goto done;
    }
    count++;
  }
  err = -ENOBUFS;
  if (iml == NULL || count >= sysctl_igmp_max_memberships)
    goto done;


Bu noktaya gelindiyse, bu durum yeni soketin yeni gruba linklendiği, dolayısıyla yeni girişin oluşturulması ve soketlere uygun gruplara linklenmesi gerektiği anlamına gelir. Bellek şimdiden ayrıldı, yalnızca yapıların gerektirdiği değişik alanlar için doğru değerleri kurmamız gerekiyor.

  memcpy(&iml->multi,imr, sizeof(*imr));
  iml->next = sk->ip_mc_list;
  iml->count = 1;
  sk->ip_mc_list = iml;
  ip_mc_inc_group(in_dev,addr);
  iml = NULL;
  err = 0;
done:
  rtnl_shunlock();
  if (iml)
    sock_kfree_s(sk, iml, sizeof(*iml));
  return err;
}


p_mc_leave_group() fonksiyonu multicast gruptan çıkıldığında uyarılır ve bir önceki fonksiyondan daha kolaydır. Arayüz ve grup adresleri alınır ve aktif soketlerde gerçekleşen girişlerin arasından aranır. Bir kez bulurlar, önermelerin numarası kararlaştırılır, burada en küçük bir işlem gruba birleştirilir. Eğer yeni değer sıfırsa,sayaç kendisi siler.

int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
{
  struct ip_mc_socklist *iml, **imlp;
  for (imlp=&sk->ip_mc_list;(iml=*imlp)!=NULL; imlp=&iml->next) {
    if (iml->multi.imr_multiaddr.s_addr==imr->imr_multiaddr.s_addr
     && iml->multi.imr_address.s_addr==imr->imr_address.s_addr &&
     (!imr->imr_ifindex || iml->multi.imr_ifindex==imr->imr_ifindex)) {
      struct in_device *in_dev;
      if (--iml->count)
        return 0;

      *imlp = iml->next;
      synchronize_bh();

      in_dev = inetdev_by_index(iml->multi.imr_ifindex);
      if (in_dev)
        ip_mc_dec_group(in_dev, imr->imr_multiaddr.s_addr);
      sock_kfree_s(sk, iml, sizeof(*iml));
      return 0;
    }
  }
  return -EADDRNOTAVAIL;
}


Diğer multicast seçenekleri çok basit şekilde yukarıda listelendi çünkü iç yapının veri alanlarında birleşim sağlanan soketlerle kullandığımız bazı değerleri kuruyor. Bu ayırımlar ip_setsockopt() fonksiyonu ile sağlanıyor..

 

Bu yazı için görüş bildiriminde bulunabilirsiniz

Her yazı kendi görüş bildirim sayfasına sahiptir. Bu sayfaya yorumlarınızı yazabilir ve diğer okuyucuların yorumlarına bakabilirsiniz.
 talkback page 

Görselyöre sayfalarının bakımı, LinuxFocus Editörleri tarafından yapılmaktadır
© Angel Lopez, FDL
LinuxFocus.org

Burayı klikleyerek hataları rapor edebilir ya da yorumlarınızı LinuxFocus'a gönderebilirsiniz
Çeviri bilgisi:
es -> -- Angel Lopez
es -> en JavierPalacios
en -> tr Ceyhun Elmas

2001-02-26, generated by lfparser version 2.9