You are on page 1of 48

Beejin Ag Programlama Klavuzu

Internet Soketlerini Kullanarak


Yazan: eviren:

Brian "Beej" Hall


<beej (at) piratehaven.org>

Emre "FZ" Sevin


<fz (at) ileriseviye.org>

zet Bu belge bir gretici olarak tasarlanm tr ve tam te ekkll bir ba vuru klavuzu degildir. Soket pro s s s gramlama konusuna ciddi ciddi merak salan bireyler tarafndan adm adm okunursa i e yarayacaktr. s

indekiler I
1. Giris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1. Kimin Iin? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2. Platform ve Derleyiciler . . . . . . . . . . . . . . . . . . . . . . . . . 1.3. Resmi Anasayfa . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4. Solaris/SunOS Programclarnn Dikkat Etmesi Gerekenler . . . . . . 1.5. Windows Programclarnn Dikkat Etmesi Gerekenler . . . . . . . . . 1.6. Eposta Politikas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.7. Yanslama . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.8. evirmenlerin Dikkatine . . . . . . . . . . . . . . . . . . . . . . . . 1.9. Telif Hakk ve Dagtm . . . . . . . . . . . . . . . . . . . . . . . . . 2. Soket Nedir? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1. Internet Soketlerinin Iki tr . . . . . . . . . . . . . . . . . . . . . . 2.2. D k Seviye Duyarszlg ve Ag Teorisi . . . . . . . . . . . . . . . . s 3. structlar ve Veri Ile Ugrasmak . . . . . . . . . . . . . . . . . . . . . . . 3.1. Veri Trlerini Dn tr! . . . . . . . . . . . . . . . . . . . . . . . . . s 3.2. IP Adresleri ve Bunlarla Ugra ma Yntemleri . . . . . . . . . . . . . s 4. Sistem agrlar veya Felaketleri . . . . . . . . . . . . . . . . . . . . . . 4.1. socket() Al Su Dosya Tanmlaycy! . . . . . . . . . . . . . . . . . 4.2. bind() Hangi Port zerindeyim? . . . . . . . . . . . . . . . . . . . 4.3. connect()Hey, sen! . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4. listen() Biri Beni Arayabilir mi Acaba? . . . . . . . . . . . . . . . . 4.5. accept() "3490 Numaral Portu Aradgnz Iin Te ekkrler" . . . . s 4.6. send() ve recv() Konu Benimle Bebegim! . . . . . . . . . . . . . s 4.7. sendto() ve recvfrom() Benimle UDPce Konu s . . . . . . . . . . 4.8. close() ve shutdown() D Yakamdan! . . . . . . . . . . . . . . . s 4.9. getpeername() Kimsiniz? . . . . . . . . . . . . . . . . . . . . . . 4.10. gethostname() Ben kimim? . . . . . . . . . . . . . . . . . . . . 4.11. DNS Sen "whitehouse.gov" de, ben de "198.137.240.92" diyeyim 5. IstemciSunucu Mimarisi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 4 4 4 4 5 6 6 6 6 7 8 9 10 11 12 12 13 15 16 16 17 18 19 20 20 20 22

Beejin Ag Programlama Klavuzu

5.1. Basit Bir Veri Ak Sunucusu . . . . . s 5.2. Basit Bir Veri Ak Istemcisi . . . . . . s 5.3. Veri Paketi Soketleri . . . . . . . . . 6. Ileri Teknikler . . . . . . . . . . . . . . . . 6.1. Bloklama . . . . . . . . . . . . . . . 6.2. select() E zamanl G/ ogullama s 6.3. Sorunlu send() Durumlar . . . . . . . 6.4. Veri Paketlemesi Hazretleri . . . . . . 7. Diger Kaynaklar . . . . . . . . . . . . . . . 7.1. man Sayfalar . . . . . . . . . . . . . 7.2. Kitaplar . . . . . . . . . . . . . . . . 7.3. Web Kaynaklar . . . . . . . . . . . . 7.4. RFCler . . . . . . . . . . . . . . . . 8. Ska Sorulan Sorular . . . . . . . . . . . 9. Son sz ve Yardm agrs . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

23 25 26 28 29 29 34 35 37 37 38 39 39 39 45

http://belgeler.org

Linux Kitaplg

2 / 48

Beejin Ag Programlama Klavuzu

zgn belgenin srm bilgileri:


1.0.0 lk srm. I 1.5.5 Son HTML srm. Agustos 1995 13 Ocak 1999 beej beej beej beej

2.0.0 6 Mart 2001 DocBook XML formatna dn trld, dzeltmeler ve eklemeler. s 2.3.1 8 Ekim 2001 client.c iindeki birka szdizimi hatas giderildi, ska sorulan sorular blmne yeni malzeme eklendi.

Bu evirinin srm bilgileri:


0.9 eviri ve ilk kontroller yapld. 15 Aralk 2002 FZ

Yasal Aklamalar
I I BU BELGE "CRETSZ" OLARAK RUHSATLANDIGI N, ERDG BLGLER N LGL KAI I II I I I I I I I NUNLARIN ZN VERDG LDE HERHANG BR GARANT VERLMEMEKTEDR. AKS YAZILI I I II I I I I I I RTLMEDG MDDETE TELF HAKKI SAHPLER VE/VEYA BASKA SAHISLAR BELI OLARAK BELI I I I I I "OLDUGU GB", ASKAR VEYA ZIMNEN, SATILABLRLG VEYA HERHANG BR AMACA I GEYI I I I I I I I I UYGUNLUGU DA DAHL OLMAK ZERE HBR GARANT VERMEKSZN DAGITMAKTADIRLAR. I I I I I I BLGNN KALTES LE LGL TM SORUNLAR SZE ATTR. HERHANG BR HATALI BLGDEN I I I I I I I I I I I I I I I I DOLAYI DOGABLECEK OLAN BTN SERVS, TAMR VEYA DZELTME MASRAFLARI SZE ATTR. I I I I I I LGL KANUNUN CBAR ETTG DURUMLAR VEYA YAZILI ANLASMA HARCNDE HERHANG BR I I I I II I I I I LDE TELF HAKKI SAHB VEYA YUKARIDA ZN VERLDG SEKLDE BELGEY DEGSTREN I I I SEKI I I I I I I I I I VEYA YENDEN DAGITAN HERHANG BR KS, BLGNN KULLANIMI VEYA KULLANILAMAMASI I I I II I I I (VEYA VER KAYBI OLUSMASI, VERNN YANLIS HALE GELMES, SZN VEYA NC SAHISLARIN I I I I I I ZARARA UGRAMASI VEYA BLGLERN BASKA BLGLERLE UYUMSUZ OLMASI) YZNDEN I I I I I OLUSAN GENEL, ZEL, DOGRUDAN YA DA DOLAYLI HERHANG BR ZARARDAN, BYLE BR I I I TAZMNAT TALEB TELF HAKKI SAHB VEYA LGL KSYE BLDRLMS OLSA DAH, SORUMLU I I I I I I I I II I I I I I I I DEGLDR. Tm telif haklar aksi zellikle belirtilmedigi srece sahibine aittir. Belge iinde geen herhangi bir terim, bir ticari isim ya da kuruma itibar kazandrma olarak alglanmamaldr. Bir rn ya da markann kullanlm s olmas ona onay verildigi anlamnda grlmemelidir.

http://belgeler.org

Linux Kitaplg

3 / 48

Beejin Ag Programlama Klavuzu

1. Giris
Hey! Soket programlama ile ba nz belada m? Btn bu ayrntlar man sayfalarndan ekip karmak iin ok s mu zor? En temel Internet programlama tekniklerini grenmek istiyorsunuz ama tonlarca struct ve bunlar bind() i levini agrmadan connect(), vs., vs.ye parametre olarak nasl geeceginiz konusunda binlerce s ayrnty grenmeye vaktiniz yok mu? Hmm, bakn burada ne var? Btn bu sinir bozucu ayrntlarla ben zamannda bogu tum ve herkesle deney s imlerimi payla mak iin can atyorum! Dogru yere geldiniz. Bu belge ortalama bir C programcsna tm bu ag s meseleleri ile ilgili temel kavramlar ve pratik uygulamalar verecek dzeydedir.

1.1. Kimin in? I


Bu belge bir gretici olarak tasarlanm tr ve tam te ekkll bir ba vuru klavuzu degildir. Soket programlama s s s konusuna ciddi ciddi merak salan bireyler tarafndan adm adm okunursa i e yarayacaktr. Bu belge kesinlikle s eksiksiz bir soket programlama klavuzu degildir. Eger su man sayfalarnn sizin iin biraz daha anlaml hale gelmesini saglarsa bu belge amacna ula m s s demektir...:)

1.2. Platform ve Derleyiciler


Bu belgedeki kodlar Linux al tran bir PC zerinde Gnunun gcc derleyicisi ile derlenmi tir. Ancak gcc derleyis s cisinin al abildigi her platformda derlenebilir. Tabii eger Windows kullanyorsanz yukarda dediklerim geerli s degildir. Bunun iin a agdaki Windows Programclarnn Dikkat Etmesi Gerekenler (sayfa: 4) blmne bakn. s

1.3. Resmi Anasayfa


Bu belgenin resmi adresi California Devlet niversitesi, Chico, http://www.ecst.csuchico.edu/ ~beej/guide/net/dir.

1.4. Solaris/SunOS Programclarnn Dikkat Etmesi Gerekenler


Solaris ya da SunOS iin derlerken gerekli i lev kitaplklarn programa baglayabilmek iin baz ek parametreler s vermeniz gerekebilir. Bunun iin lnsl lsocket lresolv parametrelerini derleme komutunuzun sonuna ekleyebilirsiniz, rnek:
$ cc o server server.c lnsl lsocket lresolv

eger hala hata alyorsanz sunu da ekleyin: lxnet. Ne i e yaradgn bilmiyorum ama grnen o ki baz s durumlarda gerekebiliyor. Problem ya ayabileceginiz bir ba ka yer de setsockopt() i levinin agrldg yerdir. Bu i levin Sos s s s laris/SunOStaki prototipi benim Linux makinamdakinden farkldr bu yzden de:
int yes=1;

yerine bunu girin:


char yes=1;

Elimde bir Sun makinas yok, yukardakileri denemedim bu bilgiler bana deneme yapp eposta gnderen insanlarn sylediklerinden ibarettir.

1.5. Windows Programclarnn Dikkat Etmesi Gerekenler


http://belgeler.org
Linux Kitaplg 4 / 48

Beejin Ag Programlama Klavuzu

Windowsdan pek ho landgm sylenemez bu yzden de bu belgeyi okuyan tm Windows programclarn s GNU/Linux, BSD ya da UNIX denemeye davet ediyorum. Bu laardan sonra, evet, rnek kodlar Windows zerinde kullanma imkannz var. ncelikle burada bahsettigim birok sistem ba lk dosyasn unutun. Tek yapmanz gereken a agdakileri pro s s gramnza katmak:
#include <winsock.h>

Bir dakika! Ayn zamanda WSAStartup() i levini de soket kitaplklar ile herhangi bir i yapmadan nce s s agrmanz gerekiyor. Bunu yapmak iin gerekli kod syle bir sey:
#include <winsock.h> { WSADATA wsaData; // if this doesnt work //WSAData wsaData; // then try this instead if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) { fprintf(stderr, "WSAStartup failed.\n"); exit(1); }

Tabii derleyicinize Winsocku da baglamasn sylemelisiniz. Bunun iin gerekli dosyann ismi genellikle sudur: wsock32.lib veya winsock32.lib veya benzer bir sey. VC++ ortamnda iseniz, bunun iin Project mensnden, Settings... ksmna gidin ve Link sekmesine gelip Object/library modules kutusunu bulun. wsock32.lib dosyasn bu listeye ekleyin. En azndan ben byle duydum. s s Ve son olarak da WSACleanup() i levini agrmanz gerekir soket kitaplg ile i iniz bittiginde. Ayrntl bilgi iin derleyicinizin yardm belgelerine bakn. Bunu yaptgnzda bu belgedeki rneklerin hemen hepsi genel olarak al abilir durumda olmal belki birka s kk degi iklik yapmanz gerekebilir ama hepsi bu. Dikkat etmeniz gerekenler: Soketi kapatmak iin close() s i levini kullanamazsnz bunun iin closesocket() i levini kullanmalsnz. Ayrca select() i levi s s s sadece soket tanmlayclar iindir, dosya tanmlayclar (standart girdi iin 0 kullanlmas gibi) iin degildir. Ayn zamanda, CSocket isimli bir soket snf da mevcuttur. Ayrntl bilgi iin derleyicinizin belgelerini kar trn. s Winsock hakknda ayrntl bilgi iin su adrese bakabilirsiniz: Winsock FAQ(B3) Son olarak da bildigim kadar ile Windows ortamnda fork() isimli i lev yok ve maalesef rnek s lerde bu i levi kullanmak durumdaym. Belki de bir POSIX kitaplgna programnz baglamanz gerekes s s bilir veya CreateProcess() i levini kullanabilirsiniz. fork() i levi herhangi bir argman almaz ama CreateProcess() i levi 48 milyar argman alr. Eger bu gznz biraz korkuttu ise CreateThread() s i levi biraz daha kolay bir alternatif olabilir ancak "multithreading" tart mas bu belgenin snrlarnn tesindedir. s s Windows konusunu bylece burada kapatyoruz!

1.6. Eposta Politikas


Genellikle eposta ile gnderilen sorulara cevap vermeye al rm, bu yzden yazmaktan ekinmeyin, ancak s bu size cevap verecegim anlamna gelmez. Epey me gulm ve bazen sorunuzun cevabn tam olarak bilmiyor s olabilirim. Durum bu oldugunda mesajnz silerim ltfen bunu sahsnza ynelik bir harekete olarak alglamayn. nann bana sordugunuz her soruyu en ince ayrntsna kadar cevaplayacak kadar vaktim olmayabilir. I

http://belgeler.org

Linux Kitaplg

5 / 48

Beejin Ag Programlama Klavuzu

Basit bir kural: Sorunuz ne kadar karma k ise cevap verme ihtimalim o kadar d ktr. Eger soru kapsamn s s daraltr ve derdinizle ilgili ayrntl bilgileri de yollarsanz (platform, derleyici, hata mesajlar, vs.), cevap alma ihtimaliniz artar. Daha ayrntl bilgi iin su adresi tavsiye ederim: How To Ask Questions The Smart Way (B4). Eger cevap alamyorsanz biraz daha kurcalayn programnz ve cevab bulmaya al n. Hala zemedi iseniz s o zaman bana gene yazn ve belki o zaman elimizdeki ayrntl bilgilerle probleme bir zm bulmamz daha kolay olabilir. Simdi sizi bana nasl yazmanz ve yazmamanz konusunda yeterince egittigime gre bu klavuzla ilgili sre iinde bana ula trlan vglerin beni ne kadar motive ettigini de itiraf etmek isterim. :) Te ekkrler! s s

1.7. Yanslama
Sitemin bir yanssn barndrmak istiyorsanz memnuniyet duyarm. Eger olu turacagnz yansya ana sayfam s dan link vermek isterseniz <beej (at) piratehaven.org> adresine bir mesaj yollamanz yeterli olacaktr.

1.8. evirmenlerin Dikkatine


Eger bu belgeyi ba ka bir dile evirmek isterseniz ltfen <beej (at) piratehaven.org> adresinden benimle ileti im s s kurun bylece ana sayfadan sizin tercmenizin bulundugu sayfaya bag verebilirim. eviriye kendi isminizi ve eposta adresinizi eklemekte tereddt etmeyin. zgnm yer kstlamasndan tr sizin evirinizi kendi sitemde barndramam.

1.9. Telif Hakk ve Dagtm


Beejs Guide to Network Programming Copyright 19952001 Brian "Beej" Hall. Bu belge btnlg korundugu, ierigi degi tirilmedigi ve bu kopyalama bilgisi de yaynlandg srece herhangi s bir ortamda serbeste yeninden yaynlanabilir. gretim grevlileri bu belgeyi grencilerine tavsiye edebilirler. Bu belge herhangi bir dile tercme edilebilir yeter ki sz konusu tercme aslna sadk kalsn ve belgenin btnlgn bozmasn. Tercme, tercmeyi yapann ismini ve temas bilgilerini ierebilir. Belgedeki C kaynak kodlar kamuya aktr. leti im adresim: <beej (at) piratehaven.org>. I s

2. Soket Nedir?
Srekli "socket"lerden bahsedildigini duymu sunuzdur ve belki de bunlarn tam olarak ne anlama geldigini merak s ediyor olabilirsiniz. Soket ksaca sudur: Diger programlarla standart Unix dosya tanmlayclarn kullanarak haberle menizi saglayan bir yap. s Ne? Pekala baz Unix hackerlarnn, "Vay canna! Unixteki hemen hemen her ey bir dosya!" dedigini duymu s s olabilirsiniz. Byle konu an birinin kast ettigi aslnda Unix programlarnn, herhangi bir G/ i lemi yaptklarnda s s bunlar bir dosya tanmlaycy okuyarak ya da ona yazarak yaptklardr. Bir dosya tanmlayc basite sylemek gerekirse ak bir dosya ile ili kilendirilmi bir tamsaydr. Ancak (i in pf noktas da buras), sz konusu bu ak s s s dosya diskteki normal bir dosya olabilecegi gibi ayn zamanda bir ag baglants, bir FIFO, bir ubirim ya da ba ka s herhangi bir veri kaynag olabilir. Gerekten de Unix ortamnda her sey bir dosyadr! yleyse Internet zerinden ba ka bir programla ileti im kurmak isterseniz bunu bir dosya tanmlayc zerinden yapacaksnz, inann buna. s s

http://belgeler.org

Linux Kitaplg

6 / 48

Beejin Ag Programlama Klavuzu

"Peki bay ok bilmi , ag ileti imi iin kullanacagm bu dosya tanmlayc nerede?" gibi bir soru aklnza gelmemi s s s olabilir ancak ben gene de cevabn vereyim ki iiniz rahat etsin: Bu dosya tanmlaycya ula mak iin socket() s sistem i levini agrmanz gerekir. Bu i lev size soket tanmlaycy dndrr ve siz de bunu ve tabii send() s s (B5), man recv (B6)) isimli soket i levlerini kullanarak istediginiz sekilde ileti imizini ile recv() (man send s s kurarsnz. "Hey, bir dakika!" diyebilirsiniz simdi. "Eger bir dosya tanmlayc sz konusu ise o halde tanr a kna neden her s s s zaman kullandgm normal read() ve write() i levlerini kullanarak soketler zerinden ileti im kuramayaym ki?" Ksa cevap: "Evet tabii ki!" Uzun cevap ise "Evet, mmkn ama send() ve recv() i levleri veri ileti iminde s s ok daha fazla kontrol saglar ve i inizi kolayla trr." s s Srada ne var? Buna ne dersiniz: e it e it soket vardr. Mesela DARPA Internet adresleri (Internet Soketleri), s s yerel bir dgmdeki (node) yol isimleri (Unix Soketleri), CCITT X.25 adresleri (X.25 Soketleri ki inann bunlar bilmeseniz de olur) ve kullandgnz Unix srmne bagl daha pek ok soket tipi. Bu belge sadece birinci tr soketleri ele almaktadr, yani: Internet Soketleri.

2.1. Internet Soketlerinin ki tr I


Bu da ne? ki tr Internet soketi mi var? Evet. Sey, aslnda hayr. Yalan syledim. Daha ok var ama sizi I korkutmak istemedim. Size sadece iki tr soketten bahsedecegim. Sadece "Ham Soketler"in (Raw Sockets) ok gl oldugunu belirttigim bu cmle d nda yani, bir ara bunlara da gz atarsanz iyi olur. s Pekala, gelelim su iki tr sokete. Bir tanesi "Veri Ak Soketleri"; digeri ise "Veri Paketi Soketleri" ve artk biz bun s lara sras ile "SOCK_STREAM" ve "SOCK_DGRAM" diyecegiz. Veri paketi soketleri bazen "baglantsz soketler" s olarak da isimlendirilir. (Her ne kadar eger isterseniz bunlara connect() i levi ile baglanabilecek olsanz da. Detayl bilgi iin a agdaki connect() (sayfa: 15) maddesine bakn.) s Veri ak soketleri gvenilir iki ynl ileti im kanallardr. Eger bu tr bir sokete sra ile "1, 2" bilgilerini gns s derirseniz, bunlar kanaln diger ucundan "1, 2" seklinde kar. Ayn zamanda bu ileti im olas hatalara kar da s s korumaldr. Kar la acagnz her trl hatann kaynag sizin karman orman aklnz olacaktr ve burada bunlar s s tart maya niyetim yok. s s Stream soketleri gerek hayatta ne i imize yarar? Hmm, sanrm telnet diye bir program duymu sunuzdur, s degil mi? ste bu program veri ak soketlerini kullanr. Yazdgnz tm karakterler sizin yazdgnz srada iletilme I s lidir yle degil mi? Ayn zamanda web tarayclar da HTTP protokol ile ileti im kurarken veri ak soketleri s s araclg ile sayfa bilgilerini ekerler. Gerekten de eger bir web sitesine telnet ile 80 numaral port zerinden baglanr ve "GET /" komutunu yollarsanz web sitesi size HTML ierigini yollayacaktr. Veri ak soketleri bu kadar sorunsuz bir veri ileti imini nasl gerekle tirir? Bunun iin "Aktarm Denetim Pros s s tokol" (Transmission Control Protocol) isimli kurallar dizisinden yararlanrlar ki siz bunu "TCP" olarak da duymu s olabilirsiniz (bkz. RFC793(B8) bu belge TCP ile ilgili ok ayrntl bilgi ierir.) TCP yollanan verinin sral ve dzgn gitmesini saglar. "TCP"yi daha nce "TCP/IP" ksaltmasnn bir paras olarak duymu olabilirsiniz ki "IP" de "In s ternet Protocol" sznn ksaltmasdr (bkz. RFC791(B9).) IP kurallar dizisi temelde Internet ynlendirme ile ilgilidir, veri btnlgnn korunmas ile ilgili pek kural iermez. Harika. Peki veri paketi soketleri? Neden bunlara baglantsz deniyor? Mesele nedir ksaca? Neden bunlarn "gvenilmez" oldugu syleniyor? Bakn, bilmeniz gereken baz gerekler var: eger bir veri paketi yollarsanz bu hedene ula abilir de ula mayabilir de. Gnderdiginiz srada ula mas garanti edilemez. Ancak eger hedefe s s s ula rsa paketin ierdigi bilgi hatasz olacaktr. s Veri paketi soketleri de ynlendirme iin IP protokoln kullanrlar ancak TCPden faydalanmazlar onun yerine "Kullanc Veri Paketi Protokok" (User Datagram Protocol) veya "UDP" isimli protokol kullanrlar (bkz. RFC 768(B10).)

http://belgeler.org

Linux Kitaplg

7 / 48

Beejin Ag Programlama Klavuzu

Neden baglantszdrlar? Aslnda byledirler nk veri ak soketlerinde oldugu gibi baglanty srekli ak s tutmanz gerekmemektedir. Sadece bir paketi olu turur, tepesine gidecegi adresi syleyen bir IP ba lg yap trr s s s ve onu yollarsnz. Herhangi bir baglant amaya gerek yoktur. Bu tip soketler genellikle paket paket iletilen veri iin kullanlr. Bu tip soketleri kullanan rnek uygulamalardan bazlar: tftp, bootp, vs. "Yeter artk!" diye bagrdgnz duyar gibiyim. "Eger veri paketlerinin yolda kaybolma ihtimali varsa nasl olur da yukarda saydgn programlar al r?!" Bak dnyal dostum bu saydgm programlarn hepsi UDP protokol s zerine kendi protokollerini yerle tirirler. Mesela, tftp protokolne gre gnderilen her paket iin kar tarafn s s "aldm!" (bir "ACK" paketi) paketini geri yollamas gerekir. Eger orjinal paketin gndericisi mesela 5 saniye iinde cevap alamazsa o zaman paketi yeniden yollar, taa ki ACK cevabn alana kadar. ste bu "aldm" prosedr I SOCK_DGRAM uygulamalarnda ok nemlidir.

2.2. Dsk Seviye Duyarszlg ve Ag Teorisi


Protokol katmanlarndan bahsettigime gre artk aglarn nasl al tgna dair gerekleri grenmenin ve s SOCK_DGRAM paketlerinin nasl olu turulduguna dair rnekler vermenin zaman geldi. Pratik olarak bu blm s atlayabilirsiniz, ancak buray okursanz iyi bir temel bilgiye sahip olursunuz. Sekil 1. Veri Paketlemesi (data encapsulation)

Protokollerin Veriyi Paketlemesi Hey ocuklar, Veri Paketleme konusunu grenme zaman! Bu ok ok nemli. O kadar nemli o kadar nemli ki burada yani Chico Eyaletinde ag teknolojilerine dair bir kurs alrsanz bu konu ile mutlaka kar la rsnz ;). s s Temelde konu su: bir paket dogar, sonra bu paket nce muhatap oldugu ilk protokol tarafndan (mesela TFTP protokol) ile bir ba lk (ve ender olarak da olsa bir dipnot ile) kullanlarak paketlenir (kapsle konur), ardndan s tm bu ygn (TFTP ba lg da dahil) bir sonraki protokoln (rn. UDP) kurallarna gre paketlenir, sonra IP ve s en sonundaki en alt katman olan donanm katmanndaki ziksel protokol ile (rn. Ethernet) paketlenir. Ba ka bir bilgisayar bu paketlenmi paketi aldgnda nce donanm Ethernet ba lgn karr, ardndan i letim s s s s sistemi ekirdegi IP ve UDP ba lklarn alr ve ardndan da TFTP program TFTP ba lgn alr ve iindeki veriye s s eri ir. s Artk su kt ne sahip Katmanl Ag Modeli (Layered Network Model) kavramndan bahsedebilirim. Bu ag modeli diger modellere pek ok stnlg bulunan bir ag i levselliginden bahseder. Mesela yazdgnz soket s programnn tek bir harni bile degi tirmenize gerek kalmadan bu program farkl ziksel donanmlar zerinde s al trabilirsiniz (seri, thin Ethernet, AUI, her ne ise) nk d k seviyedeki programlar sizin yerinize ayrntlar s s hallederler. Ag donanmnn ziksel detaylar ve topolojisi soket programcsn ilgilendirmez. Daha fazla laf kalabalg yapmadan bu mthi modelin katmanlarn liste olarak vereyim, ag ile ilgili snava s girerseniz i e yarayabilir: s

Uygulama Sunum Oturum Ta ma s Ag Veri Baglants Fiziksel Linux Kitaplg 8 / 48

http://belgeler.org

Beejin Ag Programlama Klavuzu

Fiziksel katman donanmla ilgilidir (seri, Ethernet, vs.). Uygulama katman ziksel katmandan alabildigine uzaktr kullanclar ag ile bu katmanda temas kurar. Akas bu model o kadar geneldir ki eger isterseniz bu modeli arabanza bile uygulayabilirsiniz. Unix ile daha uyumlu bir katmanl model syle yazlabilir:

Uygulama Katman (telnet, ftp, etc.) Konaktan Konaga Ta ma Katman (TCP, UDP) s Internet Katman (IP ve ynlendirme) Aga Eri im Katman (Ethernet, ATM ya da her ne ise) s

Bu a amada sz konusu katmanlarn veri paketlenmesinin hangi a amalarna kar lk geldigini grebiliyor ols s s malsnz. Tek bir paketi olu turmak iin ne kadar ok i yaplmas gerektigini grdnz m! Aman allahm! stelik paket s s ba lk bilgilerini de cat komutunu kullanarak elle girmeniz gerekiyor! Saka saka! Tek yapmanz gereken eger s veri ak soketi kullanyorsanz send() ile veriyi gndermek. Eger veri paketi soketi kullanyorsanz bu sefer s s de yaplmas gereken paketi uygun sekilde paketleyip sendto() i levini kullanarak bunu yollamak. ekirdek sizin iin Ta ma katmann ve Internet katmann kurar, donanmnz da Aga Eri im Katmann halleder. Ah, s s modern teknoloji. Ag teorisi ile ilgili ksa dersimiz burada sona eriyor. Ah evet tabii ki ynlendirmeyle ilgili sylemem gereken seyler vard: unutun! Bundan bahsetmeyecegim. Ynlendirici (router) IP ba lgn eker ynlendirme tablosuna s bakar, seim yapar, vs. vs. vs. Eger gerekten merakl iseniz IP RFC(B11) belgesine bakn. Bunu grenmezsiniz lmezsiniz.

3. structlar ve Veri le Ugrasmak I


Hele skr bu a amaya gelebildik. Artk biraz programlamadan bahsedebiliriz. Bu blmde soket arayzleri s tarafndan kullanlan pek ok veri trn ele alacagm nk bunlar gerekten nemli. Kolay olanlarla ba layalm: bir soket tanmlayc. Bir soket tanmlayc a agdaki trdendir: s s
int

Evet, gayet klasik, al k oldugumuz basit bir int. s ste bu a amadan itibaren i ler biraz gariple meye ba lyor bu yzden de dikkatlice okuyun ve bana gvenin. I s s s s lk bilmeniz gereken: iki tr byte sralamas vardr: en nemli baytn (ki buna bazen ktet de denir) nce geldigi I sralama veya en nemli baytn sonra geldigi sralama. Bu sralamalardan birincisine "Ag Bayt Sralamas" (Network Byte Order) (1) denir. Baz makinalar isel olarak veriyi kendi belleklerinde bu sekilde depolar, bazlar ise bu sray dikkate almaz. Bir seyin Ag Bayt Sralamasna gre sralanmas gerektigini syledigimde htons() gibi bir i lev agrmanz gerekecek ("Konak Bayt Sralamas"ndan [Host Byte Order] "Ag Bayt Sralamas"na s dn trebilmek iin). Eger "Ag Bayt Sralamas"ndan bahsetmiyorsam o zaman ilgili veriyi oldugu gibi yani s "Konak Bayt Sralamas" dzeninde brakmanz gerekir. My First Struct TM struct sockaddr. Bu veri yaps pek ok trde soket iin soket adres bilgisini barndrr:
struct sockaddr { unsigned short char };

sa_family; sa_data[14];

// adres ailesi, AF_xxx // protokol adresinin 14 byte

http://belgeler.org

Linux Kitaplg

9 / 48

Beejin Ag Programlama Klavuzu

sa_family pek ok degerden birini alabilir ama bizim rnegimizde AF_INET olacak. sa_data ise soketle ilgili
hedef adres ve port numaras bilgilerini barndrr. Bunun garip oldugunu kabul ediyorum, yani herhalde bu bilgiyi kendi ellerinizle paketleyerek sa_data degi kenine yerle tirmek istemezsiniz degil mi? s s

struct sockaddr ile ba a kabilmek iin programclar buna paralel bir yap tasarlam lar: struct s s sockaddr_in ("in" "Internet" anlamna geliyor.)
struct sockaddr_in { short int unsigned short int struct in_addr unsigned char }; sin_family; sin_port; sin_addr; sin_zero[8]; // // // // Adres ailesi Port numaras Internet adresi struct sockaddr ile ayn boyda

Bu yap soket adresi elemanlarna eri meyi kolayla trr. Dikkat etmeniz gereken bir nokta: sin_zero,(2) s s memset() i levi kullanlarak tamamen sfr ile doldurulmaldr. Buna ek ve daha da nemli olarak bir struct s sockaddr_in gstergesi struct sockaddr gstergesine dn trlebilir ve tersi de dogrudur. Yani s her ne kadar socket() i levi struct sockaddr* seklinde bir veri beklese de siz gene de struct s sockaddr_in kullanp son anda gerekli dn trmeyi yapabilirsiniz! Ayrca sin_family degi keninin de s s struct sockaddr yapsndaki sa_family degi kenine kar lk geldigini ve "AF_INET" olarak ayarlanmas s s gerektigini unutmayn. Son olarak sin_port ve sin_addr degikenlerinin de Ag Byte Srasnda bulunmalar gerektigini unutmayn! "Fakat," diye itiraz edebilirsiniz, "nasl olur da tm yap yani struct in_addr sin_addr Ag Bayt Sralamasna gre dizilebilir ki?" Bu soru tm zamanlarn en kt unionlarndan biri olan struct in_addr yapsnn dikkatli olarak incelenmesini gerektirir:
// Internet adresi (tarihi sebeplerden tr korunmakta) struct in_addr { unsigned long s_addr; // 32bit yani 4 bytes };

Evet, bir zamanlar kt bir union idi. Neyse ki gemi te kald. Eger ina degi kenini struct sockaddr_in s s trnden tanmlad iseniz ina.sin_addr.s_addr 4 bytelk Internet adresini gsterir (Ag Bayt Sralamasnda). Aklnzda bulunsun eger sizin sisteminiz kahrolas struct in_addr unionn kullanyor olsa bile yine de 4 bytelk Internet adresine tamamen benim yaptgm gibi ula abilirsiniz (bunu #definelara borluyuz). s

3.1. Veri Trlerini Dnstr!


Deminden beri su Ag ve Konak Bayt Sralamalar ile yeterince kafa si irdim simdi biraz eylem zaman! s Pekala. Dn trebileceginiz iki tr vardr: short (iki byte) ve long (drt byte). Bu i levler unsigned ve s s s varyasyonlar zerinde al r. rnegin bir short degi kenin bayt dzenini Konak Bayt Sralamasndan Ag s Bayt Sralamasna evirmek istiyorsunuz. "h" ile ba layalm ("host"), sonra "to" ve ardndan "n" ("network") son s olarak da bir "s" ("short"): htons veya htons() ("Host to Network Short" olarak okursanz hatrlamanz kolay olur). O kadar da zor saylmaz degil mi... Aptallarca olanlarn bir kenara brakrsak "n", "h", "s" ve "l" ile her trl birle imi olu turabilirsiniz. rnegin tabii s s s s ki stolh() ("Short to Long Host") gibi bir i lev yoktur. Fakat su i levler vardr:

htons() "Host to Network Short" konaktan aga short htonl() "Host to Network Long" konaktan aga long ntohs() "Network to Host Short" agdan konaga short
Linux Kitaplg 10 / 48

http://belgeler.org

Beejin Ag Programlama Klavuzu

ntohl() "Network to Host Long" agdan konaga long

Bu konuyu kavradgnz d nyor olabilirsiniz. Mesela aklnza su gelebilir: "char trnde bir verinin Bayt s Sralamasn degi tirmem gerekirse ne yapmam gerekir?" Ve sonra syle cevap verebilirsiniz: "Aman, bo ver." s s Ayrca aklnza su da gelebilir: mesela 68000 i lemcili makinanz zaten Ag Bayt Sralamasn kullandgna s gre htonl() i levini IP adreslerine uygulamanza gerek yoktur. Hakl olabilirsiniz. FAKAT eger geli tirdiginiz s s yazlm teki trl Bayt Sralamasna gre al an bir bilgisayara ta rsanz programnz kesinlikle al maz. s s s Ta nabilir programlar yazn! Unutmayn Unix dnyasndasnz! (Her ne kadar Bill Gates aksini d nmek istese s s de.) Sakn unutmayn: baytlarnz ag zerinde yolculuga karmadan nce onlar Ag Bayt Sralamasna gre dizeceksiniz. Son bir noktaya daha dikkat ekmek istiyorum: neden struct sockaddr_in yaps iindeki sin_port ve sin_addr Ag Bayt Sralamasnda olmak zorunda iken sin_family byle bir zellige sahip olmak duru munda degil? Cevab: sin_addr ve sin_port sras ile IP ve UDP katmanlarnda paketlenirler. Bu yzden Ag Bayt Sralamasnda gnderilmeleri gerekir oysa ki sin_family sadece i letim sistemi ekirdegi tarafndan s veri yapsnn barndrdg adresin trn tespit etmek iin kullanlr. Bu yzden de bu alann Konak Bayt Sralamasnda braklmas gerekir. Ayrca sin_family ag zerinden bir yere yollanmadg iin Konak Bayt Sralamasnda olabilir.

3.2. IP Adresleri ve Bunlarla Ugrasma Yntemleri


Sanslsnz nk IP adresleri ile ugra manz saglayacak bir grup i lev vardr. Yani elle hesap kitap yapp sonra s s da bunu bir long iine << i leci ile tk trmanza gerek yok. s s nce rnegin elinizde bir struct sockaddr_in ina degi keni ve bir de 10.12.110.57 seklinde bir s IP adresi oldugunu var sayalm. Bu adresi bu degi ken iine yerle tirmek istiyorsunuz. Kullanmanz gereken s s s s i lev: inet_addr(). Bu i lev bir IP adresini yukardaki gibi saylardan ve noktalardan olu an bir biemden s alp unsigned long trnde bir sayya evirir. Bu tr bir atama su sekilde yaplabilir:
ina.sin_addr.s_addr = inet_addr("10.12.110.57");

Suna dikkat edin: inet_addr() zaten dndrdg degeri Ag Bayt Sralamasna gre dizilmi olarak dndrr s yani htonl() i levini burada agrmanza gerek yok. Harika! s Yukardaki kod paras pek saglam saylmaz nk hi hata denetimi yok. Grdgnz gibi inet_addr() kili say sistemini hatrladnz m? (unsigned)1 tam hatal bir durumla kar la nca 1 degerini dndrr. I s s da su IP adresine kar lk gelir: 255.255.255.255! Bu da yayn adresidir! Aman dikkat. Hata kontroln s dzgn bir sekilde yapmay sakn ihmal etmeyin. Aslnda inet_addr() yerine kullanabileceginiz daha gzel bir i lev var: inet_aton() ("aton"u, "ascii to s network" olarak okuyun):
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int inet_aton(const char *cp, struct in_addr *inp);

Bir rnek vermek gerekirse: bu i lev struct sockaddr_in yapsn paketlerken (ilerledike bu rnek size s daha da anlaml gelecek bind() (sayfa: 13) ve connect() (sayfa: 15) ksmlarna kadar sabredin.)
struct sockaddr_in my_addr; my_addr.sin_family = AF_INET; // konak bayt sralamas my_addr.sin_port = htons(MYPORT); // short, a bayt sralamas g inet_aton("10.12.110.57", &(my_addr.sin_addr));

http://belgeler.org

Linux Kitaplg

11 / 48

Beejin Ag Programlama Klavuzu

memset(&(my_addr.sin_zero), \0, 8); // geriye kalan sfrla

inet_aton(), diger tm soketbaglantl i levlerden farkl olarak, sorun kmazsa sfrdan farkl bir deger, s
sorun karsa da sfr degerini dndrr. Ve dndrlen adres inp iinde yer alr. Maalesef her platform inet_aton() i levini kullanmamaktadr. Bu yzden her ne kadar bu i levi tercih etsek s s de daha yaygn olmas itibariyle rneklerde inet_addr() kullanlacaktr. Artk IP adreslerini ikilik sisteme kolayca dn trebileceginize gre bunun tersini yapmaya ne dersiniz? Yani s mesela elinizde zaten bir struct in_addr yaps varsa ve siz bunu al k oldugunuz sayl noktal IP adresi s bieminde basmak istiyorsanz? Bu durumda kullanacagmz i lev: inet_ntoa() ("ntoa"y "network to ascii" s olarak okuyun). Su sekilde i inizi grr: s
printf("%s", inet_ntoa(ina.sin_addr));

Bu IP adresini basacaktr. Dikkat edin: inet_ntoa() argman olarak struct in_addr alr long almaz. Bir diger nemli nokta da: Bu i lev bir chara i aret eden bir gsterge dndrr. Sz konusu gsterge s s inet_ntoa() iinde statik olarak depolanan bir karakter dizisine i aret eder ve inet_ntoa() i levini her s s agr nzda son i lem grm olan IP adresinin zerine yazlr. rnegin: s s s
char *a1, *a2; . . a1 = inet_ntoa(ina1.sin_addr); a2 = inet_ntoa(ina2.sin_addr); printf("1. adres: %s\n",a1); printf("2. adres: %s\n",a2);

// burada 192.168.4.14 var // burada 10.12.110.57 var

sunu basar:
1. adres: 10.12.110.57 2. adres: 10.12.110.57

Eger birden fazla adresle i yapyorsanz ve bunlar yukarda oldugu gibi kaybetmek istemiyorsanz o zaman s strcpy() gibi bir i lev kullanarak uygun bir yere kopyalamay sakn ihmal etmeyin. s Bu konu ile syleyeceklerim simdilik bu kadar. Daha sonra "whitehouse.gov" gibi bir karakter dizisini hangi yntemlerle kar lk gelen IP adresine evirebileceginizi gsterecegim (bkz. DNS Sen "whites house.gov" de, ben de "198.137.240.92" diyeyim (sayfa: 20)).

4. Sistem agrlar veya Felaketleri


Bir UNIX bilgisayardaki ag i levselligine eri menizi anlatacagm blme ho geldiniz. Bu i levlerden birini s s s s agrdnzda i letim sistemi ekirdegi devreye girer ve d k seviyedeki i lemleri byleyici bir sekilde sizin s s s iin halleder. nsanlarn bu a amada en ok takldklar nokta bu i levleri hangi sra ile agracaklar sorusudur. Bu bakmdan I s s man sayfalar bir i e yaramaz, eger biraz ugra tysanz ne demek istedigimi biliyorsunuzdur. Bu zorlu konu s s ile ba a kabilmek iin i levleri normalde geli tirdiginiz bir programdaki agrl sralarna tam olarak (hemen s s s s hemen) uygun sekilde size sunmaya al acagm. s Bu aklamalara ek olarak orada burada birka rnek kod paras, biraz st art kurabiye (zgnm bu son ikisini siz tedarik etmelisiniz) ve tabii biraz da cesaret ile elinizdeki verileri Internet zerinden her yere nlyor s olacaksnz.

4.1. socket() Al Su Dosya Tanmlaycy!


http://belgeler.org
Linux Kitaplg 12 / 48

Beejin Ag Programlama Klavuzu

Sanrm artk daha fazla erteleyemem socket() sistem agrsndan bahsetmek zorundaym. ste o i lev: I s
#include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol);

Peki ya argmanlar? nce, domain argmanna AF_INET degeri verilmeli, tpk struct sockaddr_in yapsnda oldugu gibi. Sonra type argman ekirdege ne tr bir soket sz konusu oldugunu syler: SOCK_STREAM veya SOCK_DGRAM. Son olarak da protocol argmanna "0" degerini verelim ki socket(), type degi kenine kar lk gelen uygun protokol seebilsin. (Dikkat: Bahsettigimden daha ok domain ve type s s vardr. Bkz. socket() man sayfas. Ayrca protocol degerini grenmenin "daha iyi" bir yntemi vardr. Bkz. getprotobyname() man sayfas.)

socket() i levi size bir soket tanmlayc dndrr ve artk siz bunu daha sonraki i levlerinize parametre olarak s s geebilirsiniz. Eger bir hata olu ursa i lev 1 degerini dndrr. Bu durumda errno isimli global degi ken hata s s s kodunu tutar (bkz. perror() man sayfas.)
Baz belgelerde mistik bir PF_INET ifadesi grebilirsiniz, korkmayn. Normalde bu canavar gnlk hayatta pek kar nza kmaz fakat gene de kendisinden biraz bahsedeyim. Uzun zaman nce adres ailesinin (AF_INETdeki s "AF" "Address Family" manasndadr) pek ok protokol destekleyebilecegi d nlm t ( PF_INETdeki "PF" s s "Protocol Family" manasndadr). Ancak byle bir sey olmad. Yani dogru olan, AF_INET degerini struct sockaddr_in yapsnda kullanmanz ve PF_INETi ise socket() agrrken kullanmanzdr. Ancak pratik olarak AF_INETi her yerde kullanabilirsiniz. Bu i in stadlarndan W. Richard Stevens kitabnda byle yaptg s iin ben de burada byle yapacagm. Peki tamam ok gzel de bu soket ne i e yarar? Tek ba na bir i e yaramaz tabii, ltfen okumaya devam edin s s s ve diger sistem agrlarn grenin ki ta lar yerine otursun. s

4.2. bind() Hangi Port zerindeyim?


Bir soket edindikten sonra bunu makinanzdaki bir "port" ile ili kilendirmek isteyeceksiniz (3). Bu port numaras s dedigimiz sey i letim sistemi ekirdegi tarafndan gelen bir paketi belli bir srecin soket tanmlaycs ile s ili kilendirebilmesi iin gereklidir. Eger tek yapacagnz bir yere connect() ile baglanmaksa o zaman buna s gerek yoktur tabii. Gene de okumaya devam edin, zevk alacaksnz.

bind() sistem agrsnn zetine man komutu ile bakacak olursanz syle bir seyle kar la rsnz: s s
#include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

sockfd denilen sey socket() tarafndan dndrlen soket dosya tanmlaycsdr. my_addr degi keni s
struct sockaddr trnde bir veriye i aret eder ve bu yap da adresinizi yani port numaranz ve IP adresinizi s barndrr. addrlenin degeri sizeof(struct sockaddr) olarak verilebilir.
Vay canna. Bir seferde sindirmek iin biraz fazla degil mi? Bir rnek yapalm:
#include #include #include #include <string.h> <sys/types.h> <sys/socket.h> <netinet/in.h>

#define MYPORT 3490

http://belgeler.org

Linux Kitaplg

13 / 48

Beejin Ag Programlama Klavuzu

main() { int sockfd; struct sockaddr_in my_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); // hata kontroln ihmal etmeyin! my_addr.sin_family = AF_INET; // konak bayt sralamas my_addr.sin_port = htons(MYPORT); // short, a bayt sralamas g my_addr.sin_addr.s_addr = inet_addr("10.12.110.57"); memset(&(my_addr.sin_zero), \0, 8); // yapnn geriye kalann sfrlayalm // bind() iin hata kontrol yapmay unutmayn: bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)); . . .

Burada dikkat etmeniz gereken baz seyler var: my_addr.sin_port Ag Byte Sralamasnda, ve tabii my_addr.sin_addr.s_addr de yle. Bir ba ka nokta ise en tepede agrlm olan ba lk dosyalar sistemden s s s sisteme degi iklik gsterebilir. Kesin bilgi sahibi olabilmek iin sisteminizdeki man sayfalarna bakmalsnz. s

bind() konusu ile ilgili son syleyecegim sey IP ve port edinme i lemini biraz otomaktikle tirilebilir: s s
my_addr.sin_port = 0; // kullanlmayan herhangi bir portu se my_addr.sin_addr.s_addr = INADDR_ANY; // IP adresimi kullan

Grdgnz gibi my_addr.sin_port degi keninin degerini sfr yaparak bind() i levine diyoruz ki "uygun s s s olan bir port saysn bizim iin sen se". Benzer sekilde my_addr.sin_addr.s_addr degi keninin degerini INADDR_ANY yaparak zerinde al tg makinann IP adresini almasn sylemi oluyoruz. s s Eger dikkatli bir okuyucu iseniz baz seyleri fark etmi olabilirsiniz, mesela INADDR_ANY degerini Ag Bayt s Sralamasna dn trmedim! Ne kadar da yaramaz bir programcym! Ama bildigim bir sey var: INADDR_ANY s zaten SIFIR degerine kar lk geliyor! Yani hangi srada dizerseniz dizin zaten sfr. Ancak takntl olan pro s gramclar INADDR_ANY sabitinin mesela 12 olarak belirlendigi bir paralel evrenden sz aabilirler ve orada benim kodum al maz. Tamam, sorun degil, hallederiz: s
my_addr.sin_port = htons(0); // kullanlmayan herhangi bir portu se my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // IP adresimi kullan

Sistemimiz artk o kadar ta nabilir oldu ki yani bu kadar olur. Bunu burada belirttim nk kar la acagnz kod s s s rneklerinin ogu INADDR_ANY sabitini htonl() i levinden geirmez, kafanz kar masn. s s

bind() eger bir hata karsa 1 degerini dndrr ve errno isimli hata kodu degi kenine gerekli sayy yerle tir. s s bind() i levini agrrken dikkat etmeniz gereken bir ba ka sey de sudur: port numaras olarak kk bir deger s s
semeyin. 1024n altndaki tm portlar REZERVE edilmi tir (eger superuser degilseniz!). Bu saydan ba layarak s s 65535e kadar olan saylardan birini port numaras olarak kullanabilirsiniz (tabii eger setiginiz numara ba ka s bir program tarafndan kullanlmyorsa). Bazen bir sunucuyu tekrar al trmaya kalktgnzda bind() i levinin ba arsz oldugunu ve "Adres kullanmda" s s s ("Address already in use.") mesaj verdiginiz grrsnz. Bu ne anlama gelir? Daha nce kullanlm bir soket s hala ekirdek seviyesinde takl kalm tr ve bu yzden portun kullanlmasn engellemektedir. Ya kendiliginden s iptal olmasn beklersiniz ki bu 1 dakika kadar srebilir ya da programnza bu portu her halkrda kullanmasn saglayacak kodu eklersiniz:
int yes=1; //char yes=1; // Solaris programclar bunu kullanr

http://belgeler.org

Linux Kitaplg

14 / 48

Beejin Ag Programlama Klavuzu

// "Address already in use" hata mesajndan kurtul if (setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == 1) { perror("setsockopt"); exit(1); }

bind() ile ilgili ek bilgi


Kimi durumlarda bu i lev ile hi i iniz olmaz. Mesela eger connect() ile uzaktaki bir makinaya baglanyor s s ve yerel portunuzun ne oldugu ile ilgilenmiyorsanz (telnet uygulamasnda oldugu gibi nemli olan sadece uzaktaki makinadaki port ise) ksaca connect() i levini agrrsnz ve zaten bu i lev de soketin s s bagl olup olmadgn kontrol eder ve eger soket bagl degil ise bind() i levini kullanarak bunu maki s nanzdaki kullanlmayan bir port numarasna baglar.

4.3. connect()Hey, sen!


Diyelim ki bir telnet programsnz. Sizi kullanan ki i (tpk TRON lminde oldugu gibi) size bir soket dosya s tanmlaycs edinmeniz iin komut veriyor. Siz de bu komuta uyup socket() i levini agryorsunuz. Sonra, s kullanc sizden "10.12.110.57" adresine ve "23" numaral porta baglanmanz istiyor (standart telnet portu). Aha! Simdi ne yapacaksnz? Bir program olarak sanslsnz nk tam da connect() blmndeyiz uzaktaki bir bilgisayara nasl baglanrz blm. Okumaya devam kaybedecek zaman yok, kullanc bekliyor!

connect() i levi syle bir eydir: s s


#include <sys/types.h> #include <sys/socket.h> int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

sockfd dedigimiz degi ken socket() sistem agrs tarafndan dndrlm olan soket dosya tanmlaycsnn s s degerini tutar. serv_addr ise struct sockaddr trnde bir degi kendir ve hedef port ile IP adres bilgilerini s barndrr. addrlen degi keni de sizeof(struct sockaddr) degerini alrsa iyi olur. s
Ta lar yerine oturmaya ba lad m? Hemen bir rnege gz atalm: s s
#include #include #include #include <string.h> <sys/types.h> <sys/socket.h> <netinet/in.h>

#define DEST_IP "10.12.110.57" #define DEST_PORT 23 main() { int sockfd; struct sockaddr_in dest_addr;

// hedef adres

sockfd = socket(AF_INET, SOCK_STREAM, 0); // hata denetimi yapn! dest_addr.sin_family = AF_INET; // konak bayt sralamas dest_addr.sin_port = htons(DEST_PORT); // short, a bayt sralamas g dest_addr.sin_addr.s_addr = inet_addr(DEST_IP);

http://belgeler.org

Linux Kitaplg

15 / 48

Beejin Ag Programlama Klavuzu

memset(&(dest_addr.sin_zero), \0, 8);

// yapnn geriye kalann sfrla

// connect() ilevini ardktan sonra hata denetimi yap! s g connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)); . . .

Sklsanz da sylemek zorundaym: connect() i levinden sonra mutlaka hata denetimi yapn, eger hata s olu tu ise bu i lev 1 degerini dndrr ve errno degi kenine ilgili hata numarasn yerle tirir. s s s s Ayrca bind() i levini agrmadgmza da dikkat edin. Yani ksaca yerel port numaras ile ilgilenmiyoruz; s bizi ilgilendiren hedef bilgisayar (uzaktaki port). sletim sistemi ekirdegi bizim iin bir yerel port bulacaktr ve I baglandgmz bilgisayar da bu bilgiyi otomatik olarak bizden grenecektir. Siz tatl cannz zmeyin.

4.4. listen() Biri Beni Arayabilir mi Acaba?


Pekala hzmz biraz degi tirelim. Ya bir yere baglanmak istemiyorsanz ne olacak? Mesela srf zevk olsun diye s size gelen baglantlar dinlemek ve bunlarla ilgili gerekeni yapmak istediginizi var sayalm. Bu tr bir sre iki a amaldr, nce listen() ile dinler sonra da accept() ile gelen agrlar kabul edersiniz. s Dinleme i levi olduka basittir ancak gene de biraz aklama yapmak gerekiyor: s
int listen(int sockfd, int backlog);

sockfd bin kere syledigim gibi socket() sistem agrs tarafndan dndrlm olan soket dosya s tanmlaycs oluyor. backlog ise gelen agr kuyrugunda izin verilen baglant saysn gsteriyor. Bu ne mi
demek? Sey, yani gelen baglant talepleri siz onlar accept() ile kabul edene dek bir kuyrukta bekler demek ve i te bu kuyrugun ne kadar uzun olacagn ba ka bir deyi le snrn siz belirlersiniz. Pek ok sistem bu snr s s s 20 olarak belirler; siz ise mesela 5 veya 10 gibi bir deger kullanabilirsiniz. Hemen her zamanki gibi, listen() i levi hata durumunda 1 degerini dndrr ve tabii ki errno degi kenine s s de ilgili hata numarasn yazar. s s s Evet, tahmin edebileceginiz gibi listen() i levinden nce bind() i levini agrmalyz yoksa i letim sistemi ekirdegi bu dinleme i lemini geli igzel bir port zerinden yapmaya ba lar. Eger gelen baglantlar dinleyecek s s s seniz agrmanz gereken i levler sras ile syledir: s
socket(); bind(); listen(); /* accept() buraya gelecek */

Burada ok aklama ve kod yok nk zaten kendi kendini aklyor. (accept() blmnde ele alacagmz kod tabii ki daha ayrntl olacak.) Btn bu prosedrdeki en dikktali olunmas gerken nokta accept() i levinin s agrldg yer.

4.5. accept() "3490 Numaral Portu Aradgnz in Tesekkrler" I


Sk durun accept() i levi biraz gariptir! Neler oluyor? Su oluyor: ok ok uzaklardan birileri connect() s i evi ile sizin makinanzda sizin listen() ile dinlemekte oldugunuz bir porta baglanmaya al yor. Bu baglant s s talebi accept() ile kabul edilene dek kuyrukta bekleyecektir. Siz accept() i levini agrrsnz ve ona s beklemekte olan agry kabul etmesini sylersiniz. O da size yepyeni bir soket dosya tanmlaycs dndrr sadece ve sadece sz konusu baglantya zel. Evet dogru duydunuz birdenbire elinizin altnda iki soket dosya

http://belgeler.org

Linux Kitaplg

16 / 48

Beejin Ag Programlama Klavuzu

tanmlaycs oldu! Orjinal olan halen port zerinden dinleme i lemini gerekle tirmek iin kullanlyor yeni olarak s s yaratlm olan ise send() ve recv() i levlerinde kullanlmak zere emrinize amade. Hele skr! s s slevi su sekilde agrrsnz: I
#include <sys/socket.h> int accept(int sockfd, void *addr, int *addrlen);

sockfd dedigimiz listen() ile dinlediginiz soket tanmlaycdr. Basit. addr yerel olarak kullandgnz struct
sockaddr_in yapsn gsteren bir gstergedir. Gelen baglantlarla ilgili bilgiler burada barndrlacak (yani
bu yapy kullanarak gelen baglantnn hangi bilgisayar ve hangi porttan geldigini grenebilirsiniz). addrlen yerel bir tamsay degi kendir ve kullanlmadan nce accept() sizeof(struct sockaddr_in) degerini s almaldr. accept() i levi bu degerden daha fazla sayda bayt addr iine yerle tirmeyecektir. Eger sz konusu s s degerden daha azn yerle tirirse o zaman da addrlen degerini, bunu yanstacak sekilde degi tirecektir. s s Tahmin edin ne diyecegim? accept() hata durumunda 1 degerini dndrr ve errno degi kenine ilgili hata s kodunu yerle tirir. Tahmin etmi miydiniz? Gerekten? s s Biliyorum, bir seferde sindirmesi kolay degil. sterseniz a agdaki rnek koda bakalm: I s
#include #include #include #include <string.h> <sys/types.h> <sys/socket.h> <netinet/in.h> // kullanclarn balanaca port g g // kuyrukta bekleyecek balant says g

#define MYPORT 3490 #define BACKLOG 10

main() { int sockfd, new_fd; // sock_fd ile dinle, new_fd yeni balant iin g struct sockaddr_in my_addr; // benim adres bilgim struct sockaddr_in their_addr; // balanann adres bilgisi g int sin_size; sockfd = socket(AF_INET, SOCK_STREAM, 0); // hata denetimi yap! my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); my_addr.sin_addr.s_addr = INADDR_ANY; memset(&(my_addr.sin_zero), \0, 8); // // // // konak bayt sralamas short, a bayt sralamas g otomatik olarak benim IPim geriye kalan sfrla

// hata denetimi yapmay sakn unutmayn: bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)); listen(sockfd, BACKLOG); sin_size = sizeof(struct sockaddr_in); new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); . . .

Ltfen dikkat edin: new_fd seklindeki soket tanmlaycy tm send() ve recv() i levleri iin kullanacagz. s Eger sadece ve sadece tek bir baglanty kabul edecekseniz close() ile sockfd zerindeki dinleyici soketi kapatabilirsiniz bylece ayn port zerinden ba ka baglant yaplamaz, eger istediginiz gerekten bu ise. s

http://belgeler.org

Linux Kitaplg

17 / 48

Beejin Ag Programlama Klavuzu

4.6. send() ve recv() Konus Benimle Bebegim!


Bu iki i lev veri ak soketler veya baglantl veri paketi soketleri zerinden veri gndermenizi ve veri s s almanz saglar. Eger istediginiz dzenli ve baglantsz veri paketi soketleri kullanmak ise o zaman sendto() ve recvfrom() (sayfa: 18) i levleri ile ilgili a agdaki blm okumalsnz. s s

send() i levi su sekilde agrlr: s


int send(int sockfd, const void *msg, int len, int flags);

sockfd zerinden veri gndereceginiz sokettir (size socket() veya accept() tarafndan saglanm ola s bilir). msg gndermek istediginiz mesaj gsteren bir gstergedir ve len degi keni bu verinin byte cinsinden s uzunlugudur. ags parametresini 0 olarak brakabilirsiniz. (Bu parametre ile ilgili ayrntl bilgi iin bkz. send()
man sayfas.) rnek bir kod paras vermek gerekirse:
char *msg = "Beej buradaydi!"; int len, bytes_sent; . . len = strlen(msg); bytes_sent = send(sockfd, msg, len, 0); . . .

send() deger olarak gnderilen bayt miktarn dndrr bu sizin gnderilmesini istediginiz miktardan az
olabilir! Grdgnz gibi siz ona bir ygn veri gndermesini sylersiniz ancak o bazen bunun tamam ile ba a kamayabilir. Elinden geldigi kadarn gnderir ve geriye kalan veriyi yeniden gndermek sizin sorums s s lulugunuzdadr. Unutmayn, eger send() i levinin dndrdg deger len degi kenindeki deger kadar degilse yi haberlere gelince: Eger paket kkse gndermek istediginiz verinin geriye kalann gndermek sizin i inizdir. I s (1k civar) bu i lev byk ihtimalle tm veriyi bir seferde gnderebilecektir. Her zamanki gibi hata durumunda s 1 degerini dndrr ve errno kresel degi kenine hata kodunu yazar. s

recv() i levi da pek ok bakmdan yukardaki i leve benzer: s s


int recv(int sockfd, void *buf, int len, unsigned int flags);

sockfd zerinden okuma i lemini gerekle tireceginiz sokettir, buf okunan verinin yazlacag bellek blgesinin s s ba lang adresini gsteren gstergedir, len ise verinin yazlacag tamponun (buffer) azami boyudur ve ags s
yine 0 degerini alabilir (Ayrntl bilgi iin recv() man sayfasna baknz).

recv() okunduktan sonra tampona yazlan bayt miktarn dndrr ya da eger bir hata olu tu ise 1 degerini s
dndrp errno degi keninini degerini belirler. s s s Bir dakika! recv() 0 degerini dndrebilir! Bunun tek bir anlam vardr: kar taraf baglanty kesmi ! Dndrlen degerin 0 olmas recv() i levinin size "kar taraf baglanty kesti" mesajn vermesi demektir. s s Btn bunlar anlamak kolayd degil mi? Artk verilerinizi soketler zerinden yollayp alabilirsiniz! Vay be! Artk siz bir Unix Ag Programlama Uzmansnz!

4.7. sendto() ve recvfrom() Benimle UDPce Konus


"Buraya dek ok gzeldi," dediginizi duyar gibiyim, "fakat bu bilgileri baglantsz veri paketi soketleri zerinde nasl kullanabilirim ki?". No problemo, amigo. ste derdine are. I

http://belgeler.org

Linux Kitaplg

18 / 48

Beejin Ag Programlama Klavuzu

UDP soketleri uzaktaki bir konaga bagl olmadgndan klavuz paketi yollamadan nce hangi bilgiyi vermemiz gerekiyor? Dogru tahmin! Hedef adres! Ksaca:
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);

send() i levine ne kadar da benziyor degil mi? Tek fark fazladan iki bilgi paras var. to dedigimiz s struct sockaddr trnde bir degi keni gsteren i aretidir (normalde struct sockaddr_in s s
trndedir ve siz son anda gerekli tr dn mn yaparsnz) ve hedef IP adresi ile port numarasn barndrr. s tolen degi keni sizeof(struct sockaddr) degerini almaldr. s Tpk send() gibi, sendto() i levi de gnderilen bayt miktarn dndrr (bu beklediginizden az olabilir tabii s ki!) ve eger hata oldu ise 1 degerini dndrr. Tahmin edebileceginiz gibi recv() ve recvfrom() i levleri birbirlerine ok benzerdir. Ksaca recvfrom() s i levine bakarsak: s
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

Benzer oldugunu sylemi tim yani: recv() i levinde oldugu gibi, sadece birka ek degi kene ihtiyac var. s s s from yerel bir struct sockaddr trnde degi kenin adresini gsteren gstergedir ki bu degi ken de s s mesajn geldigi ilgili makinann IP adresini ve port numarasn barndracaktr. fromlen yerel ve int trnde I bir gstergedir ve sz konusu degi kenin almas gereken ilk deger sizeof(struct sockaddr)dir. slev, s al p bir deger dndrnce fromlen degi keni from degi kenindeki adresin boyunu depoluyor olacaktr. s s s

recvfrom() i levi okudugu bayt saysn veya bir hata olu mas durumunda 1 degerini dndrr (ve errno s s
degi kenine uygun hata kodunu yerle tirir). s s Unutmayn, eger connect() ile bir UDP soketine baglant kurarsanz send() ve recv() i levlerini kul s lanmanzda bir saknca yoktur. Soketin kendisi hala bir baglantsz veri paketi soketidir ve gidip gelen paketler de hala UDP protokoln kullanr. Fakat soket arayz otomatik olarak sizin yerinize gerekli hedef ve kaynak bilgisini pakete ekler.

4.8. close() ve shutdown() Ds Yakamdan!


Vay be! Deminden beri send() ile veri gnderip recv() ile de veri okuyorsunuz ve artk yoruldunuz. Soket tanmlaycnz ile ili kilendirilmi olan baglanty kesmenin zamandr. Kolay var. Al k oldugunuz Unix dosya s s s tanmlayc kapatma i levi olan close() i levini kullann: s s
close(sockfd);

Bylece artk bu sokete ne yazlabilir ne de buradan veri okunabilir. Diger uta bunlar yapmaya al an ki i artk s s bir hata mesaj ile kar la acaktr. s s Eger soket kapatma i lemi zerinde biraz daha deentim sahibi olmak isterseniz o zaman shutdown() i levini s s tercih edebilirsiniz. Bu i levi kullanarak ileti im kanaln tek ynl ya da ift ynl olarak kapatabilirsiniz ( s s close() i levi iki tara olarak keser). slev syledir: s I
int shutdown(int sockfd, int how);

sockfd kapatmak istediginiz soket dosya tanmlaycsdr ve how degi keni de su degerlerden birini alabilir: s

0 Bundan sonraki okumalara izin verme 1 Bundan sonraki gndermelere (yazmalara) izin verme 2 Bundan sonraki gndermelere ve okumalara izin verme (close() i levinin yaptg gibi) s
Linux Kitaplg 19 / 48

http://belgeler.org

Beejin Ag Programlama Klavuzu

shutdown() ba arl olarak grevini tamamlarsa 0 dndrr ama eger bir hata ile kar la rsa 1 dndrr s s s
(ve errno degi kenine hata kodunu yazar). s s Eger shutdown() i levini baglantsz veri paketi soketleri zerinde kullanrsanz bu soketler artk send() ve recv() i levleri tarafndan kullanlamaz hale gelirler (bunlar, connect() ile baglanmak istediginizde s kullanabileceginizi unutmayn). Bir ba ka nemli nokta da: shutdown() aslnda dosya tanmlaycsn kapatmaz sadece kullanlabilirligini s degi tirir. Soket tanmlaycsn gerekten iptal etmek istiyorsanz close() kullanmalsnz. s Yapacak bir ey yok. s

4.9. getpeername() Kimsiniz?


Bu i lev o kadar kolay ki! s Yani gerekten o kadar kolay ki ayr bir blm hak ediyor mu bilemiyorum.Neyse gene de yazdm i te. s

getpeername() baglantl veri ak soketinin diger tarafnda kim oldugunu syler: s


#include <sys/socket.h> int getpeername(int sockfd, struct sockaddr *addr, int *addrlen);

sockfd baglantl veri ak soketinin tanmlaycsdr, addr, struct sockaddr (veya struct s sockaddr_in) trndeki bir gstergedir ki bu da ileti imin diger ucundaki konak ile ilgili bilgileri tutar. ads drlen, int trndeki gstergedir, almas gereken ilk deger ise sizeof(struct sockaddr) olarak verilir.
Bu i lev hata durumunda 1 degerini dndrr ve errno degi kenine gerekli degeri yazar. s s Bir kere kar tarafn adres bilgisine eri tikten sonra inet_ntoa() veya gethostbyaddr() i levleri ile s s s daha fazla bilgi edinebilirsiniz. Hayr, onlarn login ismini grenemezsiniz. (Tamam, tamam. Eger diger bilgisayar identd srecini al tryor ise bu mmkndr. Ancak bu konumuz d nda (4) s s

4.10. gethostname() Ben kimim?


getpeername() i evinden daha kolay bir i lev varsa o da gethostname() i levidir. Programnzn zerinde s s s al tg konagn ismini dndrr. Bu isim daha sonra gethostname() tarafndan makinanzn IP adresini s
tespit etmek iin kullanlabilir. Bundan daha eglenceli bir sey olabilir mi? Aslnda aklma geliyor ama soket programlama ile ilgili degil. Neyse devam edelim:
#include <unistd.h> int gethostname(char *hostname, size_t size);

Argmanlar gayet basit: hostname i lev agrldktan sonra bilgisayarn ismini barndracak karakter dizisinin s gstergesidir ve size degi keni de hostname dizisinin bayt cinsinden uzunlugudur. s sler yolunda giderse, i lev 0 degerini dndrr ve hata olu ursa da 1 degerini dndrp errno degi kenini I s s s gerekli sekilde ayarlar.

4.11. DNS Sen "whitehouse.gov" de, ben de "198.137.240.92" diyeyim


Eger DNSin ne oldugunu bilmiyorsanz syleyeyim: "Domain Name System" yani "Alan Ad Sistemi" demek. Ksaca siz ona kolayca hatrlayabildiginiz adresi verirsiniz o da size buna kar lk gelen IP adresini verir (ki siz s de bu bilgiyi bind(), connect(), sendto() ve diger i levleri agrrken kullanabilesiniz). Bylece biri: s

http://belgeler.org

Linux Kitaplg

20 / 48

Beejin Ag Programlama Klavuzu

$ telnet whitehouse.gov

komutunu girdiginde telnet yazlm connect() i levine verilmesi gereken "198.137.240.92" bilgisine s eri ebilir. s Peki bu nasl al r? Bunun iin gethostbyname() i levini kullanacaksnz: s s
#include <netdb.h> struct hostent *gethostbyname(const char *name);

Grdgnz gibi bu i lev struct hostent trnde bir gsterge dndrr. Sz konusu trn ayrntl yaps s da syledir:
struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; }; #define h_addr h_addr_list[0]

Bu karma k degi kenin iindeki alanlarn aklamalarna gelince: s s

h_name Konagn resmi ismi. h_aliases Sz konusu konagn alternatif isimleri, NULL ile sonlandrlm karakter dizileri seklinde. s h_addrtype Dnen adresin tr, genellikle AF_INET degerini alr. h_length Byte cinsinden adresin uzunlugu. h_addr_list Konagn ag adresinin sfr sonlandlmal dizisi. Konak adresleri ag bayt sralamasna
sahiptir.

h_addr h_addr_list listesindeki ilk adres.

gethostbyname() al tktan sonra iini doldurdugu struct hostent trnden bir gsterge dndrr. s
Eger hata olu ursa NULL dndrr. (Fakat errno degi keni ile ilgili herhangi bir i lem yapmaz bunun yerine s s s h_errno degi keni kullanlr. Ayrntl bilgi iin a agdaki herror() i levine bakn.) s s s Peki tm bu bilgileri nasl kullanacagz? Bazen okuyucuya bilgi ygnn verip onu bununla ba ba a s s brakmak yeterli olmaz (bilgisayar belgelerini okuyanlar ne demek istedigimi anlyorlardr). Bu i levi kullanmak s d ndgnzden daha kolaydr. s ste rnek bir program (B17): I
/* ** getip.c konak isminden IP adresini elde edilmesi */ #include #include #include #include #include #include <stdio.h> <stdlib.h> <errno.h> <netdb.h> <sys/types.h> <sys/socket.h>

http://belgeler.org

Linux Kitaplg

21 / 48

Beejin Ag Programlama Klavuzu

#include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { struct hostent *h; if (argc != 2) { // komut satrnda hata denetimi fprintf(stderr,"usage: getip konak_ismi\n"); exit(1); } if ((h=gethostbyname(argv[1])) == NULL) { herror("gethostbyname"); exit(1); } // konak bilgilerini al

printf("Konak ismi: %s\n", h>h_name); printf(" IP Adresi: %s\n", inet_ntoa(*((struct in_addr *)h>h_addr))); return 0; }

gethostbyname() sz konusu oldugunda perror() i levini hata mesajn basmak iin kullanamazsnz s s (nk errno gerekli degeri almaz). Bunun yerine herror() i levini kullanmalsnz.
Aklama basit: Dogrudan ilgilendiginiz makinann Internet adresini verirsiniz ("whitehouse.gov") ve gethostbyname() i levi de al p i ini bitirdikten sonra size struct hostent trnde bir degi ken s s s s dndrr. Buradaki tek gariplik sudur: IP adresini basarken kullanmanz gereken h>h_addr, char* trndedir ama inet_ntoa() i levi struct in_addr trnde bir degi ken isteme konusunda srarc oldugu iin nce s s h>h_addr degigkenini struct in_addr* trne evirdim ve ardndan veriye ula tm. s

I 5. stemciSunucu Mimarisi
stemcisunucu dnyasnda ya yoruz, bunu kabul et dostum. Ag ortamndaki hemen her sre ya da uyguI s lama yle ya da byle sunucu sreleriyle konu up aldklar cevaplara gre i yapyor ya da tersi oluyor. s s Mesela telnet programn ele alalm. Siz uzaktaki bir konagn 23 numaral portuna telnet (istemci) ile baglandgnzda o konakta da telnetd (sunucu) isimli bir program soluk alp vermeye ba lar. Bu program s gelen telnet baglantlarn dinler, size bir "login:" istemi gnderir, vs. vs. Sekil 2. Sunucustemci Etkilesimi I

Sunucustemci Etkile imi I s stemci ile sunucu arasndaki bilgi al veri i SunucuIstemci Etkile imi (sayfa: 22)de zetlenmi tir. s s I s s Dikkat etmeniz gereken noktalardan biri de sudur: istemcisunucu ifti birbirleri ile SOCK_STREAM, SOCK_DGRAM veya ba ka bir tarzda konu uyor olabilirler (yeter ki ayn dili konu sunlar). stemcisunucu ifts s s I

http://belgeler.org

Linux Kitaplg

22 / 48

Beejin Ag Programlama Klavuzu

lerine birka me hur rnek vermek gerekirse: telnet/telnetd, ftp/ftpd veya bootp/bootpd. Yani ne s zaman bir ftp program al trsanz diger tarafta ftpd gibi size hizmeti sunan bir sre vardr. s Genellikle sunucu makinada ilgili hizmet iin tek bir sunucu program al r ve bu program kendisine baglanan s birden fazla istemciye fork() i levi araclg ile hizmet eder. Sreci zetlemek gerekirse: Sunucu bir baglant s istegi iin bekleyecek, accept() i levi ile bunu kabul edecek ve fork() i levi ile bir ocuk sre yaratp veri s s al veri ini bu srece devredecek. Bir sonraki blmde inceleyecegimiz rnek sunucu yazlmn yaptg i tam s s s da yukarda anlatldg gibidir.

5.1. Basit Bir Veri Aks Sunucusu


Bu sunucunun yaptg tek bir i var: "Hello, World!\n" dizgesiniz bir veri ak baglants zerinden kar s s s tarafa yollamak. Sunucunun dzgn al p al madgn test etmek iin tek yapmanz gereken derledikten s s sonra bir pencerede al trmak ve ardndan ba ka bir terminal penceresi ap telnet yazlm ile sunucuya s s su sekilde eri mek: s
$ telnet remotehostname 3490

Burada remotehostname sunucuyu zerinde al trdgnz makinanzn addr (5). s Sunucu yazlmn C dilindeki kaynak kodu a agdaki gibidir: (B19): (Bilgi: Bir satrn sonundaki \ satrn alt satrda s devam ettigini ifade eder.)
/* ** server.c bir veri ak soketi sunucusu rnei s g */ #include #include #include #include #include #include #include #include #include #include #include <stdio.h> <stdlib.h> <unistd.h> <errno.h> <string.h> <sys/types.h> <sys/socket.h> <netinet/in.h> <arpa/inet.h> <sys/wait.h> <signal.h> // kullanclarn balanaca port g g // balant kuyruunda bekletileceklerin says g g

#define MYPORT 3490 #define BACKLOG 10

void sigchld_handler(int s) { while(wait(NULL) > 0); } int main(void) { int sockfd, new_fd; // sock_fd ile dinle, yen balanty new_fd ile al g struct sockaddr_in my_addr; // adres bilgim struct sockaddr_in their_addr; // balanann adres bilgisi g int sin_size; struct sigaction sa; int yes=1;

http://belgeler.org

Linux Kitaplg

23 / 48

Beejin Ag Programlama Klavuzu

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == 1) { perror("socket"); exit(1); } if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == 1) { perror("setsockopt"); exit(1); } my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); my_addr.sin_addr.s_addr = INADDR_ANY; memset(&(my_addr.sin_zero), \0, 8); // // // // konak bayt sralamas short, a bayt sralamas g otomatik olarak IPmi kullan geriye kalan blgeyi sifirla

if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == 1) { perror("bind"); exit(1); } if (listen(sockfd, BACKLOG) == 1) { perror("listen"); exit(1); } sa.sa_handler = sigchld_handler; // tm l sreleri kaldr sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == 1) { perror("sigaction"); exit(1); } while(1) { // ana accept() dngs sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == 1) { perror("accept"); continue; } printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr)); if (!fork()) { // ocuk sre close(sockfd); // ocuk srecin dinlemesi gerekmez if (send(new_fd, "Hello, world!\n", 14, 0) == 1) perror("send"); close(new_fd); exit(0); } close(new_fd); // ana srecin buna ihtiyac yok } return 0; }

Meraklsna not: Evet kodu tek bir byk main() i levi olarak yazdm, anla lmas basit olsun diye, ancak eger s s Linux Kitaplg 24 / 48

http://belgeler.org

Beejin Ag Programlama Klavuzu

isterseniz bunu i levlere ayrabilirsiniz. s (Bir de su sigaction() meselesi size yabanc gelebilir haklsnz. O grdgnz kod fork() ile olu turulan ocuk sreler sonlandktan sonra kalabilecek "zombi" proseslerin icabna bakmak iin var. Eger s byle bir sr zombi sre olur ve siz bir sekilde onlarn icabna bakmazsanz bunlar gereksiz yere sistem kaynaklarn kullanr ve bu da sistem yneticinizin size sinirlenmesine yol aar.) Simdi yukardaki sunucudan veri ekebilecek bir istemci program rnegine bakalm.

5.2. Basit Bir Veri Aks stemcisi I


Bu program daha da basit. Bu istemcinin tek yaptg sey komut satrndan belirleyeceginiz bir konaga 3490 numaral port zerinden baglanmak. Sonra da sunucunun gnderdigi dizgeyi alp ekrana basmak. Hemen kaynak koduna bakalm: (B20):
/* ** client.c bir veri ak soketi istemcisi rnei s g */ #include #include #include #include #include #include #include #include #include <stdio.h> <stdlib.h> <unistd.h> <errno.h> <string.h> <netdb.h> <sys/types.h> <netinet/in.h> <sys/socket.h>

#define PORT 3490 // istemcinin balanaca port g g #define MAXDATASIZE 100 // bir seferde kabul edebileceimizazami byte miktar g int main(int argc, char *argv[]) { int sockfd, numbytes; char buf[MAXDATASIZE]; struct hostent *he; struct sockaddr_in their_addr; // balanann adres bilgisi g if (argc != 2) { fprintf(stderr,"usage: client hostname\n"); exit(1); } if ((he=gethostbyname(argv[1])) == NULL) { perror("gethostbyname"); exit(1); } // konak bilgisini al

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == 1) { perror("socket"); exit(1); } their_addr.sin_family = AF_INET; // konak bayt sralamas

http://belgeler.org

Linux Kitaplg

25 / 48

Beejin Ag Programlama Klavuzu

their_addr.sin_port = htons(PORT); // short, a bayt sralamas g their_addr.sin_addr = *((struct in_addr *)he>h_addr); memset(&(their_addr.sin_zero), \0, 8); // geriye kalan sfrla if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == 1) { perror("connect"); exit(1); } if ((numbytes=recv(sockfd, buf, MAXDATASIZE1, 0)) == 1) { perror("recv"); exit(1); } buf[numbytes] = \0; printf("Received: %s",buf); close(sockfd); return 0; }

Aklnzda bulunsun eger sunucuyu al trmadan yukardaki istemciyi al tracak olursanz connect() i levi s s s "Connection refused" (Baglant reddedildi) hatas verir. ok faydal.

5.3. Veri Paketi Soketleri


Buraya dek yazlanlar anlad iseniz ok fazla aklamaya gerek yok, rnek programlarn kodunu inceleyerek kavrayabilirsiniz: talker.c ve listener.c..

listener program bir makinada al tktan sonra 4950 numaral port zerinden gelecek paketleri dinlemeye s ba lar. talker ise komut satrnda belirteceginiz bir makinann 4950 numaral portuna yine komut satrndan s
yazdgnz mesaj bir veri paketi olarak yollar.

listener.c(B21) programnn kaynak koduna bakalm:


/* ** listener.c a veri paketi soketi sunucusu rnei g */ #include #include #include #include #include #include #include #include #include <stdio.h> <stdlib.h> <unistd.h> <errno.h> <string.h> <sys/types.h> <sys/socket.h> <netinet/in.h> <arpa/inet.h> // kullanclarn balanaca port g g

#define MYPORT 4950 #define MAXBUFLEN 100 int main(void)

http://belgeler.org

Linux Kitaplg

26 / 48

Beejin Ag Programlama Klavuzu

{ int sockfd; struct sockaddr_in my_addr; // adres bilgim struct sockaddr_in their_addr; // balanann adres bilgisi g int addr_len, numbytes; char buf[MAXBUFLEN]; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == 1) { perror("socket"); exit(1); } my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); my_addr.sin_addr.s_addr = INADDR_ANY; memset(&(my_addr.sin_zero), \0, 8); // // // // konak bayt sralamas short, a bayt sralamas g otomatik olarak IPmi kullan kalan sfrla

if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == 1) { perror("bind"); exit(1); } addr_len = sizeof(struct sockaddr); if ((numbytes=recvfrom(sockfd,buf, MAXBUFLEN1, 0, (struct sockaddr *)&their_addr, &addr_len)) == 1) { perror("recvfrom"); exit(1); } printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr)); printf("packet is %d bytes long\n",numbytes); buf[numbytes] = \0; printf("packet contains \"%s\"\n",buf); close(sockfd); return 0; }

Dikkat edin ki socket() i levini agrrken SOCK_DGRAM kullandk. Ayrca bu tr soketlerde listen() s veya accept() i levlerine ihtiyacmz yok. Baglantsz veri paketi soketlerini kullanmann gzel yanlar da var s grdgnz gibi! Simdi de srada talker.c(B22) programnn kaynak kodu var::
/* ** talker.c a datagram "client" demo */ #include #include #include #include #include #include #include #include <stdio.h> <stdlib.h> <unistd.h> <errno.h> <string.h> <sys/types.h> <sys/socket.h> <netinet/in.h>

http://belgeler.org

Linux Kitaplg

27 / 48

Beejin Ag Programlama Klavuzu

#include <arpa/inet.h> #include <netdb.h> #define MYPORT 4950 // kullanclarn balanaca port g g

int main(int argc, char *argv[]) { int sockfd; struct sockaddr_in their_addr; // balanann adres bilgisi g struct hostent *he; int numbytes; if (argc != 3) { fprintf(stderr,"usage: talker hostname message\n"); exit(1); } if ((he=gethostbyname(argv[1])) == NULL) { perror("gethostbyname"); exit(1); } // konak bilgisini al

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == 1) { perror("socket"); exit(1); } their_addr.sin_family = AF_INET; // konak bayt sralamas their_addr.sin_port = htons(MYPORT); // short, a bayt sralamas g their_addr.sin_addr = *((struct in_addr *)he>h_addr); memset(&(their_addr.sin_zero), \0, 8); // kalan sfrla if ((numbytes=sendto(sockfd, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == 1) { perror("sendto"); exit(1); } printf("sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr)); close(sockfd); return 0; }

Hepsi bu kadar! Bir bilgisayarda listener programn derleyip al trn ve ba ka bir bilgisayara geip talker s s programn al trn, birbirleri ile ne kadar gzel ileti im kurduklarn gzlemleyin! s s Bu blm bitirmeden nce son bir ayrnt: daha nce baglantl veri paketi soketlerinden bahsetmi tim. Ma s dem veri paketi ileti imi ile ilgili rnek verdik o halde birka sey daha sylememe izin verin. Mesela talker s connect() i levini agryor olsun ve listenern adresini belirtmi olsun. O noktadan itibaren talker s s sadece ve sadece connect() ile belirlenen adresi kullanabilir. Bu yzden sendto() ve recvfrom() kullanmanza gerek kalmaz; send() ve recv() ile i inizi grebilirsiniz. s

http://belgeler.org

Linux Kitaplg

28 / 48

Beejin Ag Programlama Klavuzu

6. leri Teknikler I
Aslnda burada anlatacagm teknikler ok fazla ileri saylmaz ama gene de simdiye dek grdgmz bilgilerin tesinde seyler gerektiriyorlar. Dogrusunu sylemek gerekirse zaten bu a amaya dek geldiyseniz kendizi UNIX s Ag Programlama Temelleri konusunda ciddi olarak bilgili kabul edebilirsiniz! Tebrikler! Simdi sra soketlerle ilgili baz garip seyleri grenmede, cesur yeni dnyaya ho geldiniz. Aln bakalm! s

6.1. Bloklama
Bloklama. Bunu duymu olmalsnz peki anlam nedir? Kabaca sylemek gerekirse "blok" (block) szcg s "uyku" (sleep) iin kullandgmz teknik bir terim. Bunu, yukardaki listener programn al trdgnzda s grm olmalsnz. Yani program al r ve orada ylece bir paketin gelmesini bekler. Olup biten sudur: Bu s s program recvfrom() i levini agrr, ortalkta bir veri yoktur ve bu yzden recvfrom() "bloklama" yapar s (yani orada uyur) ta ki bir veri gelene kadar. Pek ok i lev blok yapar, yani uyur. accept() bloklar. Tm recv() i levleri bloklar, yani bekler. Bunu yapas s bilmelerinin sebebi ise onlara bunu yapabilmeleri iin izin verilmi olmasdr. Soket tanmlaycsn ilk a amada s s socket() ile yarattgnzda, i letim sistemi ekirdegi onu bloklayan olarak ayarlar. Eger bir soketin bloklama s yapabilmesini istemiyorsanz o zaman fcntl() i levini agrmanz gerekir: s
#include <unistd.h> #include <fcntl.h> . . sockfd = socket(AF_INET, SOCK_STREAM, 0); fcntl(sockfd, F_SETFL, O_NONBLOCK); . .

Bir soketi bloklamayan olarak ayarladgnzda o soketten bilgi alabilirsiniz. Eger bloklamayan bir soketten bir seyler okumaya kalkarsanz ve orada bir veri yoksa, bloklama yapmasna izin verilmedigi iin bir deger dndre cektir, bu deger 1 olacaktr ve errno degi keni de EWOULDBLOCK degerini alacaktr. s Ancak genelde bu sekilde bilgi edinmeye al mak pek de iyi bir kir degildir. Eger programnz srekli soketten s veri okumaya al r hale getirirseniz o zaman ok fazla i lemci zamanndan alarsnz. Okunmak zere bir s s verinin gelip gelmedigini kontrol etmenin daha sk bir yntemi vardr ve bu yntem select() i levini temel alr. s

6.2. select() Eszamanl G/ ogullama


Biraz garip olmakla birlikte bu i levin epey faydal oldugu sylenebilir. Su durumu ele alalm: siz bir sunucu s programsnz ve bir yandan gelen baglantlar dinlerken te yandan da ak olan baglantlardan akmakta olan verileri okumak istiyorsunuz. s Sorun degil, diyorsunuz, bir accept() ve birka tane de recv() i imizi grr. Agr ol dostum! Ya agrdgn accept() i levi bloklayan durumda ise? O zaman ayn anda recv() ile nasl oluyor da veri okumay s d nebiliyorsun? "O halde bloklamayan soketleri kullanrm!" Hi yak tramadm senin gibi bir programcya! s s slemci zamann deliler gibi harcamak m istiyorsun? E peki nasl yapacagz yleyse? I

select() ayn anda birden fazla soketi gzetleme imkn sunar. Bununla kalmaz ayn zamanda hangi soketin
okumak iin hazr oldugunu, hangisine yazabileceginiz, hangisinde istisnai durumlar olu tugunu da syler. s Laf kalabalgn kesip hemen i leve geiyorum, select(): s
#include <sys/time.h> #include <sys/types.h>

http://belgeler.org

Linux Kitaplg

29 / 48

Beejin Ag Programlama Klavuzu

#include <unistd.h> int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

Bu i lev dosya tanmlayc kmelerini gzlemler. zel olarak ilgilendikleri ise readfds, writefds ve exceptfdsdir. s Mesela standart girdiden ve sockfd gibi bir soket tanmlaycdan veri okuyup okuyamayacagnz merak ediy orsanz tek yapmanz gereken 0 ve sockfdyi readfds kmesine eklemek. numfds parametresi azami dosya tanmlayc art bir olarak ayarlanmaldr. Bu rnekte sockfd+1 olmaldr. nk aktr ki yukardaki deger standart girdiden (0) daha byk olacaktr.

select() al trldktan sonra readfds semi oldugunuz dosya tanmlayclardan hangisinin okumak iin s s hazr oldugunu yanstacak sekilde gncellenir. Bunlar a agdaki FD_ISSET() makrosu ile test edebilirsiniz. s
Daha fazla ilerlemeden bu kmeler ile nasl ba a kacagnz anlataym. Her kme fd_set trndedir. Bu tr s zerinde a agdaki makrolar kullanabilirsiniz: s

FD_ZERO(fd_set *set) dosya tanmlayc kmesini temizler. FD_SET(int fd, fd_set *set) kmeye fdyi ekler. FD_CLR(int fd, fd_set *set) fdyi kmeden karr. FD_ISSET(int fd, fd_set *set) fdni kme iinde olup olmadgna bakar.

Son olarak, nedir bu struct timeval? Bazen birilerinin size veri gndermesini sonsuza dek beklemek istemezsiniz. Belki de her 96 saniyede bir ekrana "Hala al yor..." mesaj basmak istersiniz (program o esnada s bir sey yapmyor olsa bile). Bu zaman yaps sizin bir sonlandrma sresi ("timeout period") belirlemenizi saglar. Eger bu sre geildi ise ve select() hala hazr bir dosya tanmlayc bulamad ise o zaman i lev (select) s dner ve bylece de siz de i inize devam edebilirsiniz. s

struct timeval yapsnn elemanlar a agdaki gibidir: s


struct timeval { int tv_sec; int tv_usec; }; // seconds // microseconds

Tek yapmanz gereken tv_seci ka saniye beklenecegine ayarlamak ve tv_useci de ka mikrosaniye bek lenecegine ayarlamak. Evet, dogru okudunuz, mikrosaniye, milisaniye degil. Bir milisaniye iinde 1,000 mikrosaniye vardr ve bir saniye iinde de 1,000 milisaniye vardr. Yani bir saniye iinde 1,000,000 mikrosaniye vardr. Tamam da neden "usec"? Buradaki "u" harnin Yunan alfabesindeki M harne benzedigi d nlm tr s s ve bu yzden "mikro"yu temsilen kullanlm tr. Bunlara ek olarak i lev dndgnde timeout ne kadar zaman s s kaldgn gsterecek sekilde gncellenmi olabilir. Bu hangi tr UNIX kullandgnza bagldr. s Vay canna! Mikrosaniye hassasiyetinde bir zamanlaycmz var! Gene de siz buna ok gvenmeyin. Standart Unix zamandilimi yakla k 100 milisaniyedir, yani struct timeval yapsn nasl ayarlarsanz ayarlayn en s az bu kadar beklemek durumunda kalabilirsiniz. s Meraklsna not: Eger struct timeval yapsndaki degi keninizin alanlarnz 0 yaparsanz, select() i levi annda sonlanacak ve byle kmenizin iindeki tm dosya tanmlayclar taram olacaktr. Eger timeout s s parametresini NULL yaparsanz bu sefer de i lev asla zaman a mna ugramayacak ve ilk dosya tanmlayc s s hazr olana dek bekleyecektir. Son olarak: Eger belli bir kme iin beklemek sorun te kil etmiyorsa o zaman s select() i levini agrrken onu NULL olarak ayarlayabilirsiniz. s A agdaki kod paras (B23) standart girdiden bir veri gelmesi iin 2.5 saniye bekler: s

http://belgeler.org

Linux Kitaplg

30 / 48

Beejin Ag Programlama Klavuzu

/* ** select.c bir select() rnei g */ #include #include #include #include <stdio.h> <sys/time.h> <sys/types.h> <unistd.h> // standart girdi iin dosya tanmlayc

#define STDIN 0

int main(void) { struct timeval tv; fd_set readfds; tv.tv_sec = 2; tv.tv_usec = 500000; FD_ZERO(&readfds); FD_SET(STDIN, &readfds); // writefds ve exceptfds ile ilgilenmiyoruz: select(STDIN+1, &readfds, NULL, NULL, &tv); if (FD_ISSET(STDIN, &readfds)) printf("Bir tusa basildi!\n"); else printf("Zaman doldu.\n"); return 0; }

zerinde al tgnz ubirim trne bagl olarak bir tu a bastktan sonra bunun alglanmas iin ENTER tu una s s s basmanz gerekebilir. Aksi takdirde "Zaman doldu." mesaj alrsnz. Simdi bazlarnz bir veripaketi soketi zerinden veri beklemek iin bu yntemin mkemmel bir yntem oldugunu d nebilir evet haklsnz: bu ytem gerekten de mkemmel olabilir . Ancak baz UNIX trevleri selecti s bu sekilde kullanabilirken bazlar kullanamaz. Bu yzden de pratik olarak kullanmaya ba lamadan nce sis s teminizde bu konu ile ilgili man sayfalarn okuyun. Baz UNIX trevleri de struct timeval yapsndaki degi keninizi, zamana mna ne kadar sre kaldgn s s gsterecek sekilde gncelleyebilir. Bazlar ise bunu yapmaz. Eger ta nabilir programlar yazmak istiyorsanz s buna gvenmeyin. (gettimeofday() i levinden faydalann. Sama geliyor degil mi evet ama byle ben ne s yapabilirim.) Peki ya okuma kmesindeki soketlerden biri baglanty kesmi ise? Bu durumda select() bu soket iin s "okumaya hazr" mesaj verir ve siz recv() ile okumaya kalktgnzda da recv() size 0 degerini dndrr. Bylece istemcinin baglanty kesmi oldugunu anlarsnz. s Meraklsna select() ile ilgili bir bilgi daha: eger listen() ile dinlemekte olan bir soketiniz varsa bu soketin s dosya tanmlaycsn readfds kmesine yerle tirerek yeni bir baglant olup olmadgn grenebilirsiniz. ste dostlarm, sper gl select() i levinin zeti bu kadar. I s Ancak gelen yogun istek zerine yukardaki bilgileri pratige dkecegimiz bir rnek sizi bekliyor. Bu program(B24) basit bir ok kullancl "chat" sunucu olarak davranr. Derledikten sonra bunu bir pencerede

http://belgeler.org

Linux Kitaplg

31 / 48

Beejin Ag Programlama Klavuzu

al trn ve ardndan telnet ile programa baglann ("telnet hostname 9034"). Farkl farkl pencerels erden programa ayn anda birden fazla sayda baglant aabilirsiniz. Bir kere baglanp da bulundugunuz telnet ortamndan bir seyler yazp yolladgnzda, mesajnz diger bagl telnet pencerelerinde de grnmeli.
/* ** selectserver.c keyifli bir cok kullanicili chat sunucu */ #include #include #include #include #include #include #include #include <stdio.h> <stdlib.h> <string.h> <unistd.h> <sys/types.h> <sys/socket.h> <netinet/in.h> <arpa/inet.h> // dinledigimiz port

#define PORT 9034

int main(void) { fd_set master; // na dosya tanimlayici listesi fd_set read_fds; // select() icin gecici dosya tanimlayici listesi struct sockaddr_in myaddr; // sunucu adresi struct sockaddr_in remoteaddr; // istemci adresi int fdmax; // azami dosya tanimlayici numaras int listener; // dinlenen soket tanmlayc int newfd; // yeni accept()lenecek soket tanmlayc char buf[256]; // istemci verisi iin tampon int nbytes; int yes=1; // setsockopt() SO_REUSEADDR iin, aada s g int addrlen; int i, j; FD_ZERO(&master); FD_ZERO(&read_fds); // ana listeyi ve gecici listeyi temizle

// dinleyiciyi yarat if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == 1) { perror("socket"); exit(1); } // "adres zaten kullanmda" mesajndan kurtul if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == 1) { perror("setsockopt"); exit(1); } // bind myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = INADDR_ANY; myaddr.sin_port = htons(PORT); memset(&(myaddr.sin_zero), \0, 8); if (bind(listener, (struct sockaddr *)&myaddr, sizeof(myaddr)) == 1) { perror("bind");

http://belgeler.org

Linux Kitaplg

32 / 48

Beejin Ag Programlama Klavuzu

exit(1); } // listen if (listen(listener, 10) == 1) { perror("listen"); exit(1); } // dinleyici soketi ana listeye ekle FD_SET(listener, &master); // en byk dosya tanimlayicisi hatirla fdmax = listener; // so far, its this one // ana dng for(;;) { read_fds = master; // copy it if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == 1) { perror("select"); exit(1); } // mevcut baglantilari tarayip okumaya hazir olanlari tespit et for(i = 0; i <= fdmax; i++) { if (FD_ISSET(i, &read_fds)) { // bir tane yakaladik!! if (i == listener) { // handle new connections addrlen = sizeof(remoteaddr); if ((newfd = accept(listener, (struct sockaddr *)&remoteaddr, &addrlen)) == 1) { perror("accept"); } else { FD_SET(newfd, &master); // ana listeye ekle if (newfd > fdmax) { // azami miktar gncelle fdmax = newfd; } printf("selectserver: new connection from %s on " "socket %d\n", inet_ntoa(remoteaddr.sin_addr), newfd); } } else { // istemciden gelen veri icin gerekeni yap if ((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) { // bir hata var ya da istemci baglantiyi kesti if (nbytes == 0) { // baglanti kesilmis printf("selectserver: socket %d hung up\n", i); } else { perror("recv"); } close(i); // bye! FD_CLR(i, &master); // ana listeden cikar } else { // istemciden bir miktar veri geldi for(j = 0; j <= fdmax; j++) { // gelen veriyi herkese yolla! if (FD_ISSET(j, &master)) {

http://belgeler.org

Linux Kitaplg

33 / 48

Beejin Ag Programlama Klavuzu

// dinleyici ve kendimiz haric if (j != listener && j != i) { if (send(j, buf, nbytes, 0) == 1) { perror("send"); } } } } } } // O KADAR CIRKIN ki! } } } return 0; }

Ltfen dikkat edin: Yukardaki kod iinde iki dosya tanmlayc listem var: master ve read_fds. Birincisi yani, master o esnada bagl olan tm soket tanmlayclarn tutuyor ve buna ek olarak bir de dinleme grevini stlenmi s olan soketi de bnyesinde barndryor.

master diye bir liste olu turmamn sebebi select() i levinin sizin ona verdiginiz soket listesini degi tirmesi ve s s s
hangilerinin okunmaya hazr oldugunu gsterecek sekilde gncellemesi. select() agrlar arasnda baglant kmesinin bozulmam bir kopyasna ihtiyacm oldugu iin byle bir sey yaptm. Yani son anda master kmesini s read_fds kmesine kopyalyor ve select() i levini agryorum. s yi de bu ayn zamanda her yeni baglant talebinde bu baglanty master listesine eklemem gerektigi anlamna I gelmiyor mu? Tabii ki! Ve her baglant kesilmesinde de kesilen baglant ile ilgili tanmlaycy da master listesinden karmam gerekmiyor mu? Elbette!. Farknda iseniz listener soketinin ne zaman hazr oldugunu kontrol ediyorum. Hazr oldugunda bu demek oluyor ki yeni bir baglant talebi var ve ben de bunu grnce baglanty accept() ile kabul ediyor ve master listesine s ekliyorum. Benzer sekilde bir istemci baglants hazr oldugunda ve recv() i levi 0 dndrdgnde anlyorum ki istemci baglanty kapatm ve bu yzden onu master listesinden karmalym. s Ancak eger istemci recv() i levi ile sfrdan farkl bir deger dndrdgnde de biliyorum ki okunmu olan bir s s veri ygn var. Bu veriyi alyorum ve sonra da master listesi zerindeki elemanlar zerinden tek tek dola p s alm oldugum veriyi diger istemcilere yolluyorum. s Ve dostlarm i te size sper gl select() i levinin o kadar da basit olmayan aklamas. s s

6.3. Sorunlu send() Durumlar


Hatrlarsanz send() ve recv() Konu Benimle Bebegim! s (sayfa: 17) blmnde send() i levinin s sizin istediginiz kadar veriyi bir anda gnderemeyebileceginden bahsetmi tim. Tam olarak byle yani siz ondan s 512 byte gndermesini istersiniz ama o sadece 412 tanesini yollar. Peki geriye kalan 100 bayta ne oldu? Bu veriler hala bizim kk tampon blgemizde gnderilmeyi bekliyorlar. Kontrolnz d ndaki bir takm sebes plerden tr i letim sistemi ekirdegi mevcut veriyi bir seferde gndermemeye karar verdi ve i ba a d t. s s s s Sorunu halletmek iin syle bir i lev kullanabilirsiniz: s
#include <sys/types.h> #include <sys/socket.h> int sendall(int s, char *buf, int *len) {

http://belgeler.org

Linux Kitaplg

34 / 48

Beejin Ag Programlama Klavuzu

int total = 0; // gnderdigimiz byte miktari int bytesleft = *len; // eksik kalan byte miktari int n; while(total < *len) { n = send(s, buf+total, bytesleft, 0); if (n == 1) { break; } total += n; bytesleft = n; } *len = total; // gnderilen toplam bayt miktar return n==1?1:0; // sorun varsa 1, ilem tamamsa 0 dner s }

Bu rnekte, s zerinden veriyi gndermek istedigimiz soketi, buf veriyi barndran bellek blgesini (buffer) ve len de tampondaki byte saysn gsteren sayya i aret eden int trnde bir gstergedir. s Hata durumunda i lev 1 degerini dndrr (ve errno hata degi keni de send() i levi sayesinde gerekli s s s hata kodunu barndrr.) Ayrca gnderilebilmi olan byte says da len parametresinden depolanr. Bu say s sizin gndermek istediginiz sayya e it olacaktr (hata olu mas durumu haricinde). sendall() i levi verinin s s s tamamn yollamak iin elinden geleni yapacaktr ancak bir hata ile kar la rsa size geri dnecektir. s s Hemen bir rnek verelim:
char buf[10] = "Beej!"; int len; len = strlen(buf); if (sendall(s, buf, &len) == 1) { perror("sendall"); printf("We only sent %d bytes because of the error!\n", len); }

Peki ya verinin sadece bir ksm diger tarafa eri ebildiginde diger tarafta ne olup biter? Eger gelen paketlerin s boyu degi ken ise bunlar alan taraf bir paketin ne zaman bittigini, digerinin ne zaman ba ladgn nasl anlar? s s Evet, gerek dnya senaryolar insanlar biraz d nmeye zorlar. Byk ihtimalle yukardaki problemlerle ba a s s kabilmek iin yapmanz gereken veriyi paketlemek (encapsulate) olacaktr (veri paketleme blm (sayfa: 8)n hatrladnz m?) Ayrntlar iin okumaya devam edin!

6.4. Veri Paketlemesi Hazretleri


Veri paketlemesi de ne demek oluyor? En basit anlamna bakacak olursak bu su anlama gelir: Verinin ba na s ya onu tanmlayan bir ba lk bilgisi koyacaksnz ya uzunluk bilgisi ya da her ikisi birden. s Ba lk deyip durdugumuz sey neye benzer? Bu tamamen size kalm ve projeden projeye degi ebilen bir seydir. s s s Ama! Bu aklamalar biraz havada kalmad m? Tamam. Mesela ok kullancl bir chat program geli tirdiginizi ve bu programn da SOCK_STREAM trnden s soketler kullandgn var sayalm. Kullanclardan biri bir sey dediginde sunucuya gitmesi gereken iki bilgi paras vardr: Kim dedi ve ne dedi? Buraya kadar gzel. "Problem ne?" diye soruyor olabilirsiniz. Problem su: Gelip giden mesajlarn uzunlugu degi ken. "Ali" isimli biri "Selam" diyebilir ve sonra da "Veli" isimli s biri "naber moruk?" diyebilir.

http://belgeler.org

Linux Kitaplg

35 / 48

Beejin Ag Programlama Klavuzu

Bu durumda siz de send() ile gelen verileri tm istemcilere yollarsnz yle degil mi ve yolladgnz veri de su sekilde olur:
A l i S e l a m V e l i N a b e r m o ru k ?

Ve byle srp gider. Peki istemci bir paketin bitip digerinin ba ladgn nasl anlayacak? Eger isterseniz tm s paketlerin boyunu sabit yapabilirsiniz ve sonra da sendall() i levini agrrsnz ( yukarda bir rnegi var s (sayfa: 34)). Fakat bu bant geni ligini bo yere harcamak demektir! Yani herhalde send() ile sadece Alinin s s "Selam" demesi iin 1024 byte gndermek istemeyiz degil mi? ste bu yzden veriyi ufak tefek bir ba lk ve paket yaps ile paketleriz. Hem sunucu hem de istemci verinin nasl I s paketlenecegini (marshal) ve bu paketin nasl alacagn (unmarshal) bilir. Sk durun nk tam da su andan itibaren bir sunucu ile istemcinin hangi kurallara gre ileti im kuracagn belirleyen bir protokol tanmlamaya s ba lyoruz! s Simdi var sayalm ki kullanc ad en fazla 8 karakter boyunda olabiliyor ve eger daha ksa ise geriye kalan blge \0 ile dolduruluyor. Ve sonra varsayalm ki mesaj uzunlugu degi ken olabiliyor ve maksimum 128 karaktere s izin veriyoruz. Buna gre rnek bir pakete bakalm: 1. len (1 byte, unsigned) Paketin toplam boyu, 8 baytlk kullanc ismi ve chat mesaj dahil. 2. name (8 byte) Kullanc ismi, gerekirse sonu NULL ile doldurulmu . s 3. chatdata (nbyte) Gnderilecek mesajn kendisi. En fazla 128 byte olabilir. Paket boyu bu verinin boyu art 8 (kullanc ismi blmnn uzunlugu) olarak hesaplanabilir. Neden sz konusu veri alanlar iin srasi ile 8 byte ve 128 byte snrlarn setim? Tamamen keyme kalm , s bana yeterince uzun grnd. Ama belki de sizin ihtiyalarnz iin 8 byte ok az gelebilir ve siz de 30 byte uzunlugunda bir isim alan kullanabilirsiniz. Size kalm . s Yukardaki paket tanmlamasn kullanarak ilk paketimizin grnts suna benzeyecektir (onaltlk ve ASCII):
0D (uzunluk) 41 6C 69 00 00 00 00 00 A l i (dolgu) 53 65 6C 61 6D S e l a m

Ve ikincisi de benzer sekilde:


13 (uzunluk) 56 65 6C 69 00 00 00 00 V e l i (dolgu) 4E 61 62 65 72 6D 6F 72 75 6B 3F N a b e r m o r u k ?

(Uzunluk bilgisi de elbette Ag Byte Sralamasna uygun depolanmaldr. Ancak mevcut rnekte tek bir byte oldugu iin ok nemli degil. En genel durumda ise sakn unutmayn ki tm ikili dzendeki tamsaylarnz Ag Byte Sralamasna gre dizilmi olmaldr.) s Bu veriyi yollarken gvenli bir sekilde, mesela sendall() (sayfa: 34) gibi bir i levle yollamalsnz. Bylece s s s birok kez send() i levini agrm olmak gerekse de gittiginden emin olabilirsiniz. Benzer sekilde bu veriyi aldgnzda zmek iin biraz i yapmanz gerekir. En genel durumda verinin ancak s bir ksmnn gelmi olabilecegini gz nnde bulundurmalsnz (misal sadece "00 13 56 65 6C" size ula m s s s olabilir Veli isimli kullancdan. Bu ilk para grdgnz gibi eksiktir ve verinin tamamna eri ene dek birka kez s s daha recv() i levini agrmanz gerekebilir. yi de nasl? Paketin en ba na paket uzunlugu konmu oldugundan en ba tan itibaren bir paketin orjinal I s s s uzunlugunu biliriz. Ayn zamanda biliriz ki azami paket boyu da 1+8+128 olarak hesaplanabilir yani toplam olara 137 byte (nk biz byle tanmladk). Bu durumda yapabileceginiz seylerden biri iki paketi barndrabilecek byklkte bir dizi tanmlamaktr. Buras sizin al ma diziniz olacak ve paketler buraya vardka onlar buradan alp dzenleyeceksiniz. s

http://belgeler.org

Linux Kitaplg

36 / 48

Beejin Ag Programlama Klavuzu

recv() i levini her agr nzda gelen veriyi al ma dizisine aktarrsnz ve paketin tamamlanp tamamlans s s
madgna bakarsnz. Yani dizi iindeki byte miktarnn paket boyuna e it mi yoksa ondan byk m oldugunu s kontrol edersiniz (+1 nk ba lktaki uzunluk kendisi iin kullanlan 1 bytelk uzunlugu iermez). Eger tampons daki byte says 1den az ise o zaman paket tam degildir ak olarak. Bu durumu zel olarak ele almalsnz, nk bu ilk byte plktr ve paket boyu iin ona gvenemezsiniz. Paket tamamlandgnda artk onun zerinde istediginiz i lemi gerekle tirebilirsiniz. Onu kullanabilir, al ma s s s dizinizden karabilirsiniz. Nasl? Kafanzda evirip evirmeye ba ladnz m? Sk durun simdi ikinci darbe geliyor: bir paketi sonuna kadar s okumakla kalmayp ayn esnada bir sonraki paketin de bir ksmn son recv() agrsnda okumu olabilirsiniz. s ste al ma tamponunu Yani al ma blgenizde bir tam paket ve bir de ardndan gelen bir ksmi paket vardr! (I s s biraz geni tutun dememin sebebi bu idi. Yani iki paketi tutabilecek kadar i te simdi o durum gerekle ti!) s s s lk paketin boyunu bildiginize ve gelen bytelar da takip ettiginize gre bu saylar kullanarak al ma tampoI s nunuzdaki baytlardan hangisinin ilk pakete hangisinin de ksmi pakete ait oldugunu tespit edebilirsiniz. Birin cisi ile ugra may bitirince onu al ma dizisinden karp bir sonraki paketin parasn tampon ba langcna s s s ta yabilirsiniz ve bylece tampon da bir sonraki recv() agrs iin hazr hale gelir. s (Baz okuyucular belki fark etmi tir, ksmi olarak gelen ikinci paketi tampon ba na ta mak biraz vakit alabilecek s s s bir i tir ve program buna gerek duymamas iin dngsel tampon (circular buffer) kullanacak sekilde kodlanabilir. s Maalesef dngsel tamponla ilgili tart ma bu makalenin alan d na d mektedir. Gerekten merak ettiyseniz s s s Veri Yaplar ile ilgili gzel bir kitap alp ilgili blm okuyun) Kolay oldugunu sylememi tim. Sey, aslnda sylemi tim ve yleydi. yledir, yani eger pratik yapmaya s s ba larsanz gerisi orap skg gibi gelecektir. Excalibur zerine yemin ederim yle olacagna! s

7. Diger Kaynaklar
Bu a amaya kadar geldiniz ve daha ayrntl bilgi istiyorsunuz! Btn bu ag programlama konusu ile ilgili daha s ayrntl bilgileri nereden edinebilirsiniz?

7.1. man Sayfalar


Yeni ba layanlar a agdaki man sayfalar ile i e ba layabilirler: s s s s

htonl()(B29) htons()(B30) ntohl()(B31) ntohs()(B32) inet_aton()(B33) inet_addr()(B34) inet_ntoa()(B35) socket()(B36) socket options(B37) bind()(B38) connect()(B39)
Linux Kitaplg 37 / 48

http://belgeler.org

Beejin Ag Programlama Klavuzu

listen()(B40) accept()(B41) send()(B42) recv()(B43) sendto()(B44) recvfrom()(B45) close()(B46) shutdown()(B47) getpeername()(B48) getsockname()(B49) gethostbyname()(B50) gethostbyaddr()(B51) getprotobyname()(B52) fcntl()(B53) select()(B54) perror()(B55) gettimeofday()(B56)

7.2. Kitaplar
Eski tarz al may, masaya kitab koyup harl harl okumay sevenler iin a agdakiler harika birer yol gsterici s s rol oynayacaktr. Amazon.com logosuna dikkat, btn bu utanmaz ticari yakla mn sebebi su: Siz bu link s araclg ile ne kadar ok kitap satn alrsanz Amazon.com da bana o kadar ok kredi ayor ve bylece ben de oradan kitap alabiliyorum. Yani eger a agdaki kitaplardan birini satn alacaksanz neden bana da bir faydanz s dokunmasn ki diyorum. Ayrca daha ok kitap demek sizin iin yazacagm daha ok sayda programlama rehberi demek. ;)

In Association with Amazon.com Unix Network Programming, volumes 12 W. Richard Stevens. Prentice Hall tarafndan yaynland. ISBNler, 12 iin: 013490012X(B57), 0130810819(B58). Internetworking with TCP/IP, volumes IIII Douglas E. Comer ve David L. Stevens. Prentice Hall tarafndan yaynland.ISBNler, I, II ve III iin: 0130183806(B59), 0139738436(B60), 0138487146(B61). TCP/IP Illustrated, volumes 13 W. Richard Stevens ve Gary R. Wright. Addison Wesley tarafndan yaynland. ISBNler 1, 2 ve 3 iin: 0201633469(B62), 020163354X(B63), 0201634953(B64).

http://belgeler.org

Linux Kitaplg

38 / 48

Beejin Ag Programlama Klavuzu

TCP/IP Network Administration Craig Hunt.OReilly & Associates, Inc. tarafndan yaynland. ISBN 1565923227(B65). Advanced Programming in the UNIX Environment W. Richard Stevens. Addison Wesley tarafndan yaynland. ISBN 0201563177(B66). Using C on the UNIX System David A. Curry. OReilly & Associates, Inc. tarafndan yaynland. ISBN 0937175234. Tkendi.

7.3. Web Kaynaklar


Web zerindekiler: BSD Sockets: A Quick And Dirty Primer (B67) (Unix sistem programlama ile ilgili diger konularda da ciddi bilgi ieriyor!) The Unix Socket FAQ (B68)

ClientServer Computing(B69) Intro to TCP/IP (B70) (gopher) Internet Protocol Frequently Asked Questions (B71) The Winsock FAQ (B72)

7.4. RFCler
RFCler(B73): RFC768(B74) The User Datagram Protocol (UDP) RFC791(B75) The Internet Protocol (IP) RFC793(B76) The Transmission Control Protocol (TCP) RFC854(B77) The Telnet Protocol RFC951(B78) The Bootstrap Protocol (BOOTP) RFC1350(B79) The Trivial File Transfer Protocol (TFTP)

8. Ska Sorulan Sorular


8.1. Su baslk dosyalarn nereden edinebilirim? 8.2. bind() "Address already in use" veya "Adres zaten kullanmda" mesaj verdiginde ne yapmalym? 8.3. Sistemdeki ak soketlerin listesini nasl alabilirim? 8.4. Ynlendirme tablosunu nasl grntleyebilirim? 8.5. Eger tek bir bilgisayarm varsa istemcisunucu trnde programlar nasl alstrabilirim? Bir ag program yazabilmek iin bir aga ihtiyacm yok mu? 8.6. Diger tarafn baglanty kestigini nasl tespit edebilirim? 8.7. Kendi "ping" programm nasl yazabilirim? ICMP nedir? Raw soketler ve SOCK_RAW ile daha ayrntl bilgiyi nerede bulabilirim? 8.8. Bu programlar MS Windows zerinde nasl derlerim? 8.9. Bu programlar Solaris/SunOS zerinde nasl derlerim? Derlemeye alstgmda linker srekli hata veriyor! 8.10. select() neden sinyal alr almaz dsyor?

http://belgeler.org

Linux Kitaplg

39 / 48

Beejin Ag Programlama Klavuzu

8.11. recv() islevi iin bir zamanasm mekanizmasn nasl kurabilirim? 8.12. Veriyi soket zerinden gndermeden nce nasl sifreleyip skstrabilirim? 8.13. Bir sr yerde grdgm su "PF_INET" de nedir? AF_INET ile bir baglants var mdr? 8.14. stemciden kabuk komutlarn kabul edip onlar alstran bir sunucu yazlmn nasl gelistirebilirim? I 8.15. Bir ygn veriyi bir seferde yollamaya alsyorum ama diger taraftan recv() ile okumaya kalktgmda sadece 536 veya 1460 byte geldigini gryorum. Ancak ayn denemeyi kendi makinamn zerinde iki farkl pencere ap yaptgmda sorunsuz olarak veri yollayp alabiliyorum. Bunun sebebi nedir? 8.16. Bilgisayarmda MS Windows alsyor ve elimde fork() gibi bir sistem agrs olmadg gibi struct sigaction seklinde bir yap da yok. Ne yapabilirim? 8.17. TCP/IP zerinde veriyi gvenli ve sifreli bir sekilde nasl iletebilirim? 8.18. Bir gvenlik duvarnn arkasndaym diger taraftaki insanlarn benim IP adresimi grenip benim sistemime baglanmalarn nasl saglarm? 8.1. Su baslk dosyalarn nereden edinebilirim? Eger sisteminizde bunlar mevcut degilse, muhtemelen zaten ihtiyacnz olmadg iindir. zerinde al tgnz platformun belgelerini inceleyin. Eger MS Windows ortamnda derlemeye al yor iseniz tek s s ihtiyacnz olan #include <winsock.h>. 8.2. bind() "Address already in use" veya "Adres zaten kullanmda" mesaj verdiginde ne yapmalym? Dinleyici soketler zerinde setsockopt() ile birlikte SO_REUSEADDR seenegini kullanmalsnz. bind() ile ilgili blm (sayfa: 13) ve select() ile ilgili blm (sayfa: 29) okuyup rnekleri inceleyin. 8.3. Sistemdeki ak soketlerin listesini nasl alabilirim? netstat komutunu kullann. Bu komutla ilgili ayrntlar iin ilgili man sayfasn okuyun. Basit bir rnek vermem gerekirse sadece:
$ netstat

yazarak bile epey mantkl bir kt alabilirsiniz. Buradaki asl mesele hangi soketin hangi program ile ili kili s (6) oldugunu bulmak . 8.4. Ynlendirme tablosunu nasl grntleyebilirim? Ksaca: route komutunu al trn (Linux iin bu komutun yeri genellikle /sbin dizinidir) veya s netstat r komutunu deneyin. 8.5. Eger tek bir bilgisayarm varsa istemcisunucu trnde programlar nasl alstrabilirim? Bir ag program yazabilmek iin bir aga ihtiyacm yok mu? Sanslsnz nk hemen hemen tm i letim sistemleri bir tr geridn (loopback) aygt denilen sanal s s bir ag aygt kullanr. Bu aygt i letim sistemi ekirdegine gml bir mekanizmadr ve tpk ziksel bir ag s kart gibi davranr bylece ayn makinada hem sunucu hem de istemci yazlmlar al abilir. (Bu sanal s aygt ynlendirme tablosunda "lo" olarak listelenir.) Bir rnek vermek gerekirse "goat" isimli bir bilgisayara giri yaptgnz varsayalm. Bir pencerede iss temciyi digerinde de suncuyu al trabilirsiniz. Ya da sunucuyu suna benzer bir komut ile arka planda s s s al trn: "server &" ve sonra ayn yerde istemciyi al trn. Geridn aygt dedigimiz sanal aygt siss teminizde mevcut ise (%99.9 olaslkla mevcuttur) client goat veya client goat gibi bir komutla ("localhost"un sizdeki /etc/hosts dosyasnda tanml oldugunu varsayyorum) istemci yazlmn sunucu yazlm ile ayn makina zerinde konu tugunu gzlemleyebilirsiniz. Bir aga ihtiya duymadan! s

http://belgeler.org

Linux Kitaplg

40 / 48

Beejin Ag Programlama Klavuzu

Ksaca sylemek gerekirse aga bagl olmayan bir bilgisayarda yukarda verilmi olan rnek kodlar s al trabilmek iin herhangi bir degi iklik yapmanza gerek yoktur. Ya asnnn! s s s 8.6. Diger tarafn baglanty kestigini nasl tespit edebilirim? recv() i levi yle bir durumda 0 degerini dndrr. s 8.7. Kendi "ping" programm nasl yazabilirim? ICMP nedir? Raw soketler ve SOCK_RAW ile daha ayrntl bilgiyi nerede bulabilirim? Raw soketler ile ilgili tm sorularnzn cevabn W. Richard Stevensn "UNIX Network Programming" kitaplarnda bulabilirsiniz. Ltfen klavuzun kitaplar (sayfa: 38) blmne bakn. 8.8. Bu programlar MS Windows zerinde nasl derlerim? En basit yntem su: MS Windowsu silin ve Linux ya da BSD i letim sistemini kurun. };) Peki peki s tamam, o kadar srarc iseniz Windows Programclarnn Dikkat Etmesi Gerekenler (sayfa: 4) blmne bakn. 8.9. Bu programlar Solaris/SunOS zerinde nasl derlerim? Derlemeye alstgmda linker srekli hata veriyor! Linker hatas alabilirsiniz, nk genellikle Sun Microsystems ortamnda soket kitaplklar otomatik olarak baglanmaz. Ayrntl bilgi iin Solaris/SunOS Programclarnn Dikkat Etmesi Gerekenler (sayfa: 4) blmne bakn. 8.10. select() neden sinyal alr almaz dsyor? Sinyaller genellikle bloklu sistem agrlarnn 1 degerini dndrmesine ve errno degi keninin de EINTR s degerini almasna yol aar. Sinyal i levi sigaction() ile ayarladgnzda, SA_RESTART kullan s abilirsiniz. Bylece sistem agrs kesildiginde onu yeniden ba latabilme ihtimali olur. s Dogal olarak bu her zaman i e yaramaz. s Bunun iin nerecegim en iyi zm bir goto deyimine dayanr. Bildiginiz gibi bu size yapsal programlama dersi veren profesrn tylerinin diken diken olmasna yeter de artar bile, o halde neden kullanmayasnz!
select_restart: if ((err = select(fdmax+1, &readfds, NULL, NULL, NULL)) == 1) { if (errno == EINTR) { // bir sinyal kesildi o halde yeniden baslat goto select_restart; } // gerek hata ile burada ugras: perror("select"); }

Tabii ki burada goto kullanmanz sart degil; kontrol iin ba ka yaplar da kullanabilirsiniz, ancak ben zel s olarak bu i iin goto deyiminin daha temiz oldugunu d nyorum. s s 8.11. recv() islevi iin bir zamanasm mekanizmasn nasl kurabilirim? select() (sayfa: 29) i levini kullann! Bu i lev okuyacagnz soket tanmlayclar iin bir zamana m s s s parametresi belirlemenize izin verir. Ya da bu i levselligin tamamn tek bir i lev iine su sekilde gms s melisiniz:
#include #include #include #include <unistd.h> <sys/time.h> <sys/types.h> <sys/socket.h>

http://belgeler.org

Linux Kitaplg

41 / 48

Beejin Ag Programlama Klavuzu

int recvtimeout(int s, char *buf, int len, int timeout) { fd_set fds; int n; struct timeval tv; // dosya tanmlayc listesini ayarla FD_ZERO(&fds); FD_SET(s, &fds); // zamanam iin struct timeval trndeki deikeni ayarla s g s tv.tv_sec = timeout; tv.tv_usec = 0; // veri gelene veya zamanam dolana dek bekle s n = select(s+1, &fds, NULL, NULL, &tv); if (n == 0) return 2; // zamanam! s if (n == 1) return 1; // hata // veri burada olmal, o halde normal ekilde recv() ar s g return recv(s, buf, len, 0); } // recvtimeout() rnei: g . . n = recvtimeout(s, buf, sizeof(buf), 10); // zamanam 10 saniye s if (n == 1) { // hata olustu perror("recvtimeout"); } else if (n == 2) { // zamanam! s } else { // buf iine veri geldi } . .

Dikkat edin

recvtimeout() i levi zamana m durumunda 2 degerini dndrr. Neden 0 degil? s s Hatrlayacak olursanz 0 degeri recv() i levi sz konusu oldugunda kar tarafn baglanty kestigi s s anlamna geliyordu. Bu deger kullanlm oldugu iin ve 1 de hata anlamna geldiginden za s mana m durumunu gstermesi iin 2 degerini setim. s
8.12. Veriyi soket zerinden gndermeden nce nasl sifreleyip skstrabilirim? Sifrelemeyi gerekle tirmenin kolay yollarndan biri SSL (secure sockets layer gvenlik soketleri katman) s kullanmaktr ancak bu konu bu klavuzun kapsam d ndadr. s Ancak eger sk trma ve sifreleme algoritmalarnz kullanmak istiyorsanz verinin her iki uta da adm s adm i lendigini d nmek i inizi kolayla tracaktr. Her adm veriyi belli bir sekilde dn trr. s s s s s 1. sunucu veriyi bir dosyadan (veya bir yerlerden) okur, 2. sunucu veriyi sifreler (bu ksm siz ekleyeceksiniz),

http://belgeler.org

Linux Kitaplg

42 / 48

Beejin Ag Programlama Klavuzu

3. sunucu sifrelenmi veriyi send() ile yollar. s Simdi de teki tarafa bakalm: 4. istemci recv() ile kendisine yollanan sifreli veriyi alr, 5. istemci sifreli veriyi zer yani de ifre eder (bu ksm siz ekleyeceksiniz). s Yukarda sifreleme/de ifreleme yaptgnz a amada sk trma/ama i lemleri de yapabilirsiniz. Ya da hem s s s s sifreleme hem de sk trma yapabilirsiniz! Yalnz aklnzda bulunsun, bir veriyi eger sifreleyecekseniz nce s (7) sk trn sonra sifreleyin :) s Yani istemci, sunucunun uyguladg dn mlerin tersini uygulayabildigi srece araya istediginiz kadar s dn m, i lem, i lev, vs. sokabilirsiniz. s s s Tek yapmanz gereken verdigim rnek kodda verinin gnderildigi ve alndg ksmlar tespit bunlarn nce sine sifreleme i lemini yerle tirmek. s s 8.13. Bir sr yerde grdgm su "PF_INET" de nedir? AF_INET ile bir baglants var mdr? Evet, elbette. Bunun iin ltfen socket() Al Su Dosya Tanmlaycy! (sayfa: 12) blmne bakn. 8.14. stemciden kabuk komutlarn kabul edip onlar alstran bir sunucu yazlmn nasl gelistirebilirim? I Basit olsun diye varsayalm ki istemci connect() ile baglanyor, send() ile veriyi gnderiyor ve close() ile baglanty kesiyor (yani istemci tekrar baglanana dek bir sistem agrs sz konusu olmuyor). stemcinin izledigi sre syledir: I 1. connect() ile sunucuya baglan, 2. send("/sbin/ls > /tmp/client.out"), 3. close() ile baglanty kes. Bu arada sunucu gelen veri ile muhatap olur ve onu al trr: s 1. accept() ile baglanty kabul et, 2. recv(str) ile komut dizisini al, 3. close() ile baglanty kes, 4. system(komut) ile komutu al tr. s Dikkat stemcinin sunucuya ne yapacagn sylemesi uzaktan kabuk eri imi vermek demektir. Byle bir I s yetkiye sahip olan bir insan kt seyler yapabilir. Mesela yukardaki gibi bir programda istemci "rm rf " gibi bir komut gnderirse ne olur? Sizinle ili kili alandak tm dosyalar silinir, i te budur s s olacag! Bu yzden akll olun ve kesinlikle gvenli oldugunuz programlar haricinde uzaktaki istemcinin sizin sunucunuzda hibir sey al trmasna izin vermeyin, rnegin foobar komutu gibi: s
if (!strcmp(str, "foobar")) { sprintf(sysstr, "%s > /tmp/server.out", str); system(sysstr); }

http://belgeler.org

Linux Kitaplg

43 / 48

Beejin Ag Programlama Klavuzu

foobar gvenilir ve sorunsuz bir komut olabilir ama gene de spheci olmalsnz ya istemci "foobar; rm rf " gibi bir komut dizisi yollarsa? En gvenli yntemlerden biri komuta verilen parametrelerdeki alfanmerik olmayan her karakterin (bo luk dahil) ba na nceleme karakteri ("\") koyan bir i lev yazs s s
maktr. Grdgnz gibi sunucu tarafnda istemcinin gnderdigi komutlar al trma gibi bir durum sz konusu s olunca gvenlik ok nemli bir mesele haline gelmektedir. 8.15. Bir ygn veriyi bir seferde yollamaya alsyorum ama diger taraftan recv() ile okumaya kalktgmda sadece 536 veya 1460 byte geldigini gryorum. Ancak ayn denemeyi kendi makinamn zerinde iki farkl pencere ap yaptgmda sorunsuz olarak veri yollayp alabiliyorum. Bunun sebebi nedir? MTU snrn ziksel ortamn bir seferde kaldrabilecegi azami yk miktarn a yorsunuz. Makinanzdaki s sanal geridn aygt srcs 8K ya da daha fazlasn bir seferde sorunsuz olarak iletebilir. Ancak Ethers net bir seferde ba lk bilgisi ile birlikte en fazla 1500 byte ta yabilir ve siz de bu limiti a m durumdasnz. s s s s Modem zerinden veri yollamaya kalktgnzda 576 byte snr vardr ve yine bunu tek seferde geerseniz sorun ya arsnz. s ncelikli olarak tm veriyi yolladgnzdan emin olmalsnz. (Bunun iin ltfen sendall() (sayfa: 34) ile ilgili ayrntl aklamalara bakn.) Bundan eminseniz buna ek olarak verinin tamamn okuyana dek bir s dng iinde recv() i levini agrmanz gerekir.

recv() i levini defalarca agrarak verinin tamamn alma ile ilgili ayrntl aklamalar iin ltfen s
Veri Paketlemesi Hazretleri (sayfa: 35) blmn okuyun. 8.16. Bilgisayarmda MS Windows alsyor ve elimde fork() gibi bir sistem agrs olmadg gibi struct sigaction seklinde bir yap da yok. Ne yapabilirim? Eger varsalar POSIX kitaplklar iindedirler ve bunlar da derleyiciniz ile gelmi olabilir. Ben Windows s kullanmyorum bu yzden size kesin cevap veremeyecegim. Fakat hatrladgm kadar ile Microsoftun da kullandg bir POSIX uyumluluk katman vard ve i te aradgnz fork() olsa olsa oradadr. (Hatta belki s sigaction bile.) VC++ ile gelen belgeleri "fork" veya "POSIX" iin bir tarayn ve size hangi ipularn verdigine bir bakn. Eger mantkl bir sey kamazsa fork()/sigaction ikilisini brakn ve sunu deneyin: CreateProcess(). Akas ben CreateProcess() i levi tam olarak nasl kullanlr bilmiyos rum milyarlarca argman alyor olmal ama VC++ belgelerinde hepsi aklanyor olmal. 8.17. TCP/IP zerinde veriyi gvenli ve sifreli bir sekilde nasl iletebilirim? OpenSSL projesi(B89)ne bir gz atn. 8.18. Bir gvenlik duvarnn arkasndaym diger taraftaki insanlarn benim IP adresimi grenip benim sistemime baglanmalarn nasl saglarm? Maalesef bir gvenlik duvarnn amac tam da d ardaki insanlarn dogrudan sizim makinanza s baglanmasn engellemektir. Bu sekilde ieri baglanmalar ogu durumda bir gvenlik ag olarak kabul edilir. Bu tabii ki talebinizin imknsz oldugu anlamna gelmez yani gene de gvenlik duvar zerinde connect() yapabilirsiniz tabii bir "maskeleme" ya da "NAT" veya benzer bir sey sz konusu ise. Pro gramlarnz daima baglanty sizin ba latacagnz sekilde tasarlayn, bylece i iniz kolay olur. s s Eger bu sizi tatmin etmiyorsa sistem yneticilerinize size zel bir delik amalarn syleyebilirsiniz. Gvenlik duvar, zerindeki NAT yazlm ile ya da vekil tarz bir sey ile bunu gerekle tirebilir. s

http://belgeler.org

Linux Kitaplg

44 / 48

Beejin Ag Programlama Klavuzu

Ancak ltfen unutmayn ki gvenlik duvar zerindeki bir delik hafe alnabilecek bir durum degildir. Kt niyetli ki ilere eri im hakk vermediginizden emin olmalsnz. Eger bu konularda henz acemiyseniz bana s s inann ki gvenli programlar yazmak hayal edebileceginizden ok daha zordur. Sistem yneticilerinizin benden nefret etmesine yol amayn. ;)

9. Son sz ve Yardm agrs


Evet hepsi bu kadar. Umuyorum ki burada verilen bilgilerin en azndan bir blm sizin iin geerlidir ve ok byk hatalar yapmam mdr. Aslnda, eminim hata yapm mdr. s s Bunu bir uyar kabul edin! Eger baz seyleri net olarak aktaramayp ya da tam olarak sizin sisteminize bire bir uyan rnekler veremeyip sizi zdysem zr dilerim ama bu yzden beni sulayamazsnz. Yani hukuki olarak bu belgedeki szlerimin arkasnda durdugum falan yok, ok ciddiyim. Yani btn burada yazlanlar, tamam, her bir szck, yanl olabilir! s Fakat muhtemelen o kadar da yanl degiller. Yani her sey bir yana su ag programlama mevzusu zerine epey s bir emek harcadgm syleyebilirim. Oste pek ok TCP/IP uygulamas geli tirdim, ok oyunculu oyun motorlar s yazdm, vs. Ancak gene de bir soket programlama tanrs saylmam. Sradan bir adam oldugum bile sylenebilir. Bu arada eger yapc (ya da ykc) herhangi bir ele tirisi olan varsa ltfen su adrese email gndersin ki ben de s gerekeni yapaym: <beej (at) piratehaven.org>. Btn bunlar neden yaptgm merak ediyor musunuz? Hepsini para iin yaptm. Ha ha! Hayr, hayr yani asl sebep su: pek ok ki i bana soket programlama ile ilgili bir sr soru sorup duruyordu ve ben de onlara tm s cevaplar tek bir belgede toplamay d ndgm syledigimde bana "Harika!" diyorlard. Ayrca zorluklarla elde s edilmi bu bilgi ba kalar ile payla lmazsa bence heba olur. Internet bunun iin en uygun ara gibi grnyor. s s s Herkesi benzer sekilde bilgi payla mna davet ediyorum. s Bu kadar laf salatas yeter simdi biraz program yazmaly(m|z)! ;)

Notlar
a) Belge iinde dipnotlar ve d baglantlar varsa, bunlarla ilgili bilgiler bulunduklar sayfann sonunda dipnot s olarak verilmeyip, hepsi toplu olarak burada listelenmi olacaktr. s Konsol grntsn temsil eden sar zeminli alanlarda metin geni ligine sgmayan satrlarn sgmayan s ksm karakteri kullanlarak bir alt satra indirilmi tir. Sar zeminli alanlarda karakteri ile ba layan s s satrlar bir nceki satrn devam olarak ele alnmaldr.

b)

(B3)

http://tangentsoft.net/wskfaq/ http://www.tuxedo.org/~esr/faqs/smart- questions.html http://linux.com.hk/man/showman.cgi?manpath=/man/man2/send.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/recv.2.inc http://www.rfc- editor.org/rfc/rfc793.txt http://www.rfc- editor.org/rfc/rfc791.txt http://www.rfc- editor.org/rfc/rfc768.txt

(B4)

(B5)

(B6)

(B8)

(B9)

(B10)

http://belgeler.org

Linux Kitaplg

45 / 48

Beejin Ag Programlama Klavuzu

(B11)

http://www.rfc- editor.org/rfc/rfc791.txt
Meraklsna not, Ag Bayt Sralamas ayn zamanda "Kymetlisi Ba ta Bayt Sras" (BigEndian) ve Konak s Bayt Sralamas da "Kymetlisi Sonda Bayt Sras"(LittleEndian) olarak bilinir. Burada bulunmasnn sebebi iinde bulundugu veri yapsnn boyunu struct sockaddr yapsnn boyuna tamamlamaktr. Yani eger listen() kullanacaksanz genellikle byle bir sey yapmanz beklenir zaten. Mesela bir oyun sunucusuna "telnet x.y.z port 6969" seklinde baglanmanz sylendiginde kar tarafta tam da byle bir s hazrlk yaplm tr. s Ayrntl bilgi iin baknz: RFC1413 (http://www.rfc- editor.org/rfc/rfc1413.txt).)

(1)

(2)

(3)

(4)

(B16)

http://www.rfc- editor.org/rfc/rfc1413.txt http://www.ecst.csuchico.edu/~beej/guide/net/examples/getip.c


Sunucu makina ile telneti al trdgnz makina ayn ise localhost ismini de kullanabilirsiniz. s

(B17)

(5)

(B19)

http://www.ecst.csuchico.edu/~beej/guide/net/examples/server.c http://www.ecst.csuchico.edu/~beej/guide/net/examples/client.c http://www.ecst.csuchico.edu/~beej/guide/net/examples/listener.c http://www.ecst.csuchico.edu/~beej/guide/net/examples/talker.c http://www.ecst.csuchico.edu/~beej/guide/net/examples/select.c http://www.ecst.csuchico.edu/~beej/guide/net/examples/selectserver.c http://linux.com.hk/man/showman.cgi?manpath=/man/man3/htonl.3.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man3/htons.3.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man3/ntohl.3.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man3/ntohs.3.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man3/inet_aton.3.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man3/inet_addr.3.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man3/inet_ntoa.3.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/socket.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man7/socket.7.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/bind.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/connect.2.inc

(B20)

(B21)

(B22)

(B23)

(B24)

(B29)

(B30)

(B31)

(B32)

(B33)

(B34)

(B35)

(B36)

(B37)

(B38)

(B39)

http://belgeler.org

Linux Kitaplg

46 / 48

Beejin Ag Programlama Klavuzu

(B40)

http://linux.com.hk/man/showman.cgi?manpath=/man/man2/listen.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/accept.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/send.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/recv.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/sendto.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/recvfrom.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/close.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/shutdown.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/getpeername.2. inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/getsockname.2. inc http://linux.com.hk/man/showman.cgi?manpath=/man/man3/gethostbyname.3. inc http://linux.com.hk/man/showman.cgi?manpath=/man/man3/gethostbyaddr.3. inc http://linux.com.hk/man/showman.cgi?manpath=/man/man3/getprotobyname. 3.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/fcntl.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/select.2.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man3/perror.3.inc http://linux.com.hk/man/showman.cgi?manpath=/man/man2/gettimeofday.2. inc http://www.amazon.com/exec/obidos/ASIN/013490012X/beejsguides- 20 http://www.amazon.com/exec/obidos/ASIN/0130810819/beejsguides- 20 http://www.amazon.com/exec/obidos/ASIN/0130183806/beejsguides- 20 http://www.amazon.com/exec/obidos/ASIN/0139738436/beejsguides- 20 http://www.amazon.com/exec/obidos/ASIN/0138487146/beejsguides- 20 http://www.amazon.com/exec/obidos/ASIN/0201633469/beejsguides- 20 http://www.amazon.com/exec/obidos/ASIN/020163354X/beejsguides- 20 http://www.amazon.com/exec/obidos/ASIN/0201634953/beejsguides- 20
Linux Kitaplg 47 / 48

(B41)

(B42)

(B43)

(B44)

(B45)

(B46)

(B47)

(B48)

(B49)

(B50)

(B51)

(B52)

(B53)

(B54)

(B55)

(B56)

(B57)

(B58)

(B59)

(B60)

(B61)

(B62)

(B63)

(B64)

http://belgeler.org

Beejin Ag Programlama Klavuzu

(B65)

http://www.amazon.com/exec/obidos/ASIN/1565923227/beejsguides- 20 http://www.amazon.com/exec/obidos/ASIN/0201563177/beejsguides- 20 http://www.cs.umn.edu/~bentlema/unix/ http://www.ibrado.com/sock- faq/ http://pandonia.canberra.edu.au/ClientServer/ gopher://gopher- chem.ucdavis.edu/11/Index/Internet_aw/Intro_the_ Internet/intro.to.ip/ http://www- iso8859- 5.stack.net/pages/faqs/tcpip/tcpipfaq.html http://tangentsoft.net/wskfaq/ http://www.rfc- editor.org/ http://www.rfc- editor.org/rfc/rfc768.txt http://www.rfc- editor.org/rfc/rfc791.txt http://www.rfc- editor.org/rfc/rfc793.txt http://www.rfc- editor.org/rfc/rfc854.txt http://www.rfc- editor.org/rfc/rfc951.txt http://www.rfc- editor.org/rfc/rfc1350.txt
.N.: lsof komutu bu konuda size yardmc olabilir, ayrntlar iin man sayfasna bakn. :) .N.: Yazarn burada tek bir cmle olarak syleyip getigi sey gvenlik asndan grndgnden ok daha fazla nemlidir, kullanacagnz sifreleme algoritmasna ok dikkat edin ve mutlaka ifrelemeden s

(B66)

(B67)

(B68)

(B69)

(B70)

(B71)

(B72)

(B73)

(B74)

(B75)

(B76)

(B77)

(B78)

(B79)

(6)

(7)

nce sktrma ilemini uygulayn. s s


(B89)

http://www.openssl.org/
Bu dosya (bgnet.pdf), belgenin XML biiminin TEXLive ve belgeler-xsl paketlerindeki aralar kullanlarak PDF biimine dntrlmesiyle elde edilmitir. s s

27 Subat 2007

http://belgeler.org

Linux Kitaplg

48 / 48

You might also like