Windows bir ağ işletim sistemi olarak tasarlanmıştır. Bununla beraber kendi getirdiği ve uyum sağladığı network teknolojileri mevcuttur. Ağ yapısı belli standartlar ile oluşturulmaktadır. Örneğin TCP/IP 40 sene önce geliştirilmiştir. İşletim sisteminin yeri de bu standartlar çerçevesinde bilgisayarlar arası ağ teknolojisi üzerinden haberleşmeyi açık bir şekilde sağlamaktır. Yani Windows platformunu kullanarak kendi yazılımlarımızı istediğimiz şekilde çalıştırabilmektir.
Burada her şeyden evvel Windows da 1980 li yıllarda tanımlanış olan OSI referans modeline uyum sağlar. Elbette verimlilik ve başka uyumluluk bakış açılarından dolayı Windows un bunu kendisi uygularken her yedi katman için de 1:1 tasarımsal komponentler yaratılmamıştır. Yani dışa dönük uyum sağlansa da, kendi uyarlamasında tasarımın modüllerin sorumlulukları katman dışına da çıkmaktadırlar.


OSI in uyarlandığı Windows komponentlerine baktığımızda ilk önce Network API lere ihtiyacımız vardır. Bunlar ile network ile ilgili kodumuzu geliştirebiliriz. Buna örneğin Winsock, RPC, Named Pipes ve NetBIOS gibi teknolojilerin API leri dahildir.

Winsock un en büyük farkı asenkron IO ya izin vermesidir. Aynı şekilde quality of service QoS u da mümkün kılar. Winsock Extensionları ile client ve server tarafına göre yazılımsal haberleşme uyarlanabilir. Kısaca çok basit şekilde iki makinedeki yazılımlarımız arasında network bağlantısını kurduktan sonra, yazılımlar lokalde çalışırmış gibi çok hızlı haberleşebilir. Winsock/WSK ile ilgili aşağıda da aydınlatıcı bilgiler bulabilirsiniz.

RPC
de transport bakış açımız ön planda değildir. Genelde IRP ile IO yapmak isteriz ve network üzerinden de IO yaptığımızda client tarafında redirector ile file sistemin uzakta olduğunu aslında gizleriz. RPC de odak daha çok çalıştırılan kodun network de farklı makineler üzerinde çalışsa da, sanki bir makinede çalışıyormuş kadar kolay bir hale getirebilmektir. Yani RPC altyapısını kullanarak yazılımın farklı makinelerde netwörksel detaylarla çok önem vermeden çalışabilmesini sağlamaktır.
Aslında procedural bir yaklaşım, sadece neyin nerede çalışacağına yazılımın alt katmanında belirlememiz gerekir ve bu da temel kolaylığıdır. Siz prosedürlerinizi hangi makinede olurlarsa olsunlar, kod akışında tek makinadaymış gibi normal oluşturursunuz. Her farklı sunucuda çalışacak kod için de bir stub ımız olur. Yani kısaca o prosedürü netwörkte nerede bulabileceğimizi RPC runtime altyapısına aktararmamız yeterli olur. Bu stub ları da örneğin bir DLL de toplayabiliriz.

Burada COM objelerin, netwörk için DCOM objelerin kullanılması da çok yaygındır. Tabi altında yine RPC çalışır, ama DCOM ile yazılımın kendisini kolaylaştırmış oluruz.

Named Pipes
ve Mailslot lar da örneğin protokol bağımsız çalışırlar. UNC kullanırlar ve bunların API lerini kullanarak farklı sunuculardaki processler arası iletişim sağlarız. Named Pipe ile çift yönlü garantili haberleşme sağlanabilir ve daha basit mailslot mantığı ile tek yönlü ve böylece transmission garantisi olmadan haberleşme sağlanabilir.

Yani OSI yi uyarlarken, farklı makineler arasında farklı kodların çalışmasını ve bunların haberleşmesini ve veri aktarabilmesini network API leri kullanarak sağlayabiliriz. Burada OSI in üst seviyelerinde oluruz ve örneğin protokol bağımsız çalışırız. Ama aşağıya indikçe protokolün önemi de artar.


Protokollü çalışan OSI komponentleri sağlayabilmek için, protokollerimizi taşıyabilecek, kullanılan API lerin kernel mode tarafındaki taşıyıcısı olarak görebileceğimiz transport driver interface, TDI a ihtiyacımız vardır.
Örneğin başka makineye bir IRP gönderdiğimizde, bunu bir protokol sürücüsüne aktarırız ve işte bu sürücü TDI standardına uygundur. (Örneğin tcpip.sys bir protokol sürücüsüdür.)

Bu sürücülere TDI transports diyebiliriz, ve burada network driver interface specification, NDIS protokol sürücüsüne de ihtiyacımız vardır.
Bu ndis.sys, NDIS library sidir. Yani kernelde yer alan bir fonksiyon kütüphanesidir.
Makineler arası örnek IRP ümüzü taşırken, iki tarafta da bununla ilgili işlemleri yapabilmek için bu TDI transport sürücüleri çalışır. Network adaptörün sürücüsü, NIC driver da bu NDIS standardı içinde çalıştığı için onunla da standart fonksiyonlarla haberleşebiliriz ve gerektiği gibi networksel reassembly, ack ve retransmission gibi işlemleri yapabiliriz.

Ve NDIS miniport sürücülerimiz vardır. Bunlar NDIS transportları ve adaptörler arası haberleşme için fonksiyonları tablolarlar.

TDI da ancak eski ve legacy tanımlı geçmektedir. Yerine gelen ve IPv6 destekleyen winsock kernel dir, WSK.
Socket tipi ve protokol bağımsız çalışan, spesifik API leri ile erişilebilen WSK asenkron I/O da izin vermektedir. Yani çok basit örnek vermek gerekirse, üstte I/O Manager dan gelen IRP ü WSK ilgili transport protokol sürücüsüne paketlemek için aktarabilir. WSK datagram da kullanabilir ama connetionlı bağlantı da kullanabilir. Yukarıdaki Winsock API lerde çift yönlü ve tek yönlü haberleşmenin karşılığıdır.

Daha spesifik ihtiyaçlar için Windows filtering platform WFP API leri mevcuttur. Böylece network stackin herhangi bir yerinde paket işleminde interaksiyona girmek mümkün olur. Örneğin paketleri sayabilir, scan edebilir veya sadece monitör edebilirsiniz.
Bu API lerin karşılığında da işlemi yapan WFP callout sürücülerimiz mevcuttur.


Network API leri örneğin bilgisayar ismi olarak tanılan NetBIOS için de vardır. Burada netapi32.dll ve kernel tarafında netbios.sys bize ilgili altyapıyı sunar. NetBIOS un protokolü netbios extended user interface NetBEUI protokolüdür ve NetBIOS semantiklerini tcp/ip protokolüne çeviren netbt.sys modülüdür. Örneğin yazılımınız bir netbios name resolution yaptığında, basitçe istek netapi32.dll üzerinden ve oradan ebetteki ntdll.dll üzerinden kerneldeki netbios.sys den komutları tcpip.sys sürücüsüne vermeden, netbios emülatörü netbt.sys den geçer ve tcpip protol fonksiyonlarına çevrilirler.

NetBIOS dan daha önemli tabii ki DNS dir ve sadece DNS ile çözümleme yapılamazsa NetBIOS/WINS kullanılır. WINS de yoksa, NetBIOS kendisi çözümlemeyi üstlenir.

IPv6 ile yeni bir çözümleme protokolümüz de vardır: peer name resolution protocol PNRP. Bu hem DNS kullanabilir, hem de sunucusuz çalışabilir. Her kayıt için çok daha fazla detay bilgi tutabilir ve güncellemeler real time dır. Yani DNS cache sorunu yok gibidir. Çözümlemesi dâhidir: detaya inmeden temelinde aslında ilk olarak aradığımız kaydın ID sini kimin tuttuğunu bulmaya çalışırız ve bunu düğüm noktaları üzerinden yaparız. Sonra yine düğüm noktaları üzerinden aradığımız makineyi en geç yakınındaki benzer ID ler ile kestiririz. Hedefe mantıksal kestirme algoritması izlendiği için bunu sunucusuz da yapabiliriz. Yaklaştıkça aradığımız makineyi tanıyan bir makineye sonunda denk gelip hedefe ulaşırız. PNRP hakkında detaylı bilgi için kitaba bakmanızı öneririm.


OSI ile komponentler arası ilişkiyi de sayfa 1005 de görebilirsiniz ve bu belki yukarıdaki detayların kafanızda birleşmesine yardımcı olur.


Bütün komponentlerinin modüllerinin de farklı konfigürasyonlarda birbirleri ile düzgün çalışmasını sağlayan mantığa da Binding denir. Örneğin farklı networksel OS componentleri yüklü olabilir veya olmaya bilir, farklı sürücüler yüklü olabilir, network adaptörlerin gelişmiş ayarlarının bazılarında IPv6 seçili olmayabilir vs. Binding i HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Linkage altındaki Bind değerinde tutarız. En nihayetinde de bu bizim network stackini belirler. Yani komponentlerin oluşturduğu OSI yapısının kullanılan modüllerinin aralarında düzgün çalışabilmeleri için ve stackin böylece düzgün oluşturulabilmesi için ile ilgili değişken bilgileri registry de tutarız.

Böylelikle Windows OSI layer mantığını sunar ve her katmanında yazılımsal müdahaleye izin verir.


Windows Networking teknolojilerin çok daha detaylı özetini Windows Internals 5th ed. in 12 ci bölümü ‘Networking’ altında bulabilirsiniz: http://technet.microsoft.com/en-us/sysinternals/bb963901
Okumanızı kesinlikle tavsiye ederim.

Başar Güner
Sr. Support Engineer, Microsoft

image