Unix Soketi - Hızlı Kılavuz
Soketler, aynı veya farklı makinelerde iki farklı işlem arasında iletişime izin verir. Daha kesin olmak gerekirse, standart Unix dosya tanımlayıcılarını kullanarak diğer bilgisayarlarla konuşmanın bir yoludur. Unix'te her G / Ç eylemi bir dosya tanımlayıcısı yazarak veya okuyarak yapılır. Bir dosya tanımlayıcı, sadece açık bir dosyayla ilişkili bir tam sayıdır ve bir ağ bağlantısı, bir metin dosyası, bir terminal veya başka bir şey olabilir.
Bir programcıya göre, bir soket düşük seviyeli bir dosya tanımlayıcı gibi görünür ve davranır. Bunun nedeni, read () ve write () gibi komutların, tıpkı dosyalar ve borularla yaptıkları gibi soketlerle çalışmasıdır.
Soketler ilk olarak 2.1BSD'de tanıtıldı ve daha sonra 4.2BSD ile mevcut formlarına rafine edildi. Soketler özelliği artık en güncel UNIX sistem sürümlerinde mevcuttur.
Soket Nerelerde Kullanılır?
İstemci-sunucu uygulama çerçevesinde bir Unix Soketi kullanılır. Sunucu, bir istemcinin isteği üzerine bazı işlevleri yerine getiren bir işlemdir. FTP, SMTP ve POP3 gibi uygulama düzeyindeki protokollerin çoğu, istemci ile sunucu arasında bağlantı kurmak ve ardından veri alışverişi yapmak için soketlerden yararlanır.
Soket Tipleri
Kullanıcıların kullanabileceği dört tür soket vardır. İlk ikisi en yaygın olarak kullanılır ve son ikisi nadiren kullanılır.
İşlemlerin yalnızca aynı türdeki soketler arasında iletişim kurduğu varsayılır, ancak farklı türlerdeki soketler arasındaki iletişimi engelleyen bir kısıtlama yoktur.
Stream Sockets- Ağ bağlantılı bir ortamda teslimat garantilidir. Akış soketinden üç öğe "A, B, C" gönderirseniz, bunlar aynı sırada - "A, B, C" gelir. Bu soketler, veri iletimi için TCP (İletim Kontrol Protokolü) kullanır. Teslimat imkansızsa, gönderen bir hata göstergesi alır. Veri kayıtlarının herhangi bir sınırı yoktur.
Datagram Sockets- Ağ bağlantılı bir ortamda teslimat garanti edilmez. Bağlantısızdırlar çünkü Akış Soketlerindeki gibi açık bir bağlantıya ihtiyacınız yoktur - hedef bilgileriyle bir paket oluşturur ve gönderirsiniz. UDP (Kullanıcı Datagram Protokolü) kullanırlar.
Raw Sockets- Bunlar, kullanıcıların soket soyutlamalarını destekleyen temel iletişim protokollerine erişimini sağlar. Bu soketler normal olarak datagram yönelimlidir, ancak tam özellikleri protokol tarafından sağlanan arayüze bağlıdır. Ham soketler genel kullanıcı için tasarlanmamıştır; bunlar esas olarak yeni iletişim protokolleri geliştirmekle ilgilenenler veya mevcut bir protokolün daha şifreli tesislerinden bazılarına erişim sağlamak için sağlanmıştır.
Sequenced Packet Sockets- Kayıt sınırlarının korunması dışında bir akış soketine benzerler. Bu arabirim, yalnızca Ağ Sistemleri (NS) soket soyutlamasının bir parçası olarak sağlanır ve çoğu ciddi NS uygulamalarında çok önemlidir. Sıralı paket soketleri, kullanıcının bir paket veya bir paket grubu üzerindeki Sıralı Paket Protokolü (SPP) veya İnternet Datagram Protokolü (IDP) başlıklarını, gönderilecek olan verilerle birlikte bir prototip başlığı yazarak veya tüm giden verilerle kullanılacak varsayılan bir başlık belirleme ve kullanıcının gelen paketler üzerindeki başlıkları almasına olanak sağlar.
Sırada ne var?
Sonraki birkaç bölüm, soket kullanarak Sunucu ve İstemci programları yazmadan önce temel bilgilerinizi güçlendirmek ve bir temel hazırlamak amacını taşımaktadır . Bir istemci ve sunucu programının nasıl yazılacağını görmek için doğrudan atlamak istiyorsanız, o zaman bunu yapabilirsiniz, ancak bu önerilmez. Programlamaya geçmeden önce temelinizi oluşturmak için adım adım ilerlemeniz ve bu birkaç bölümü tamamlamanız şiddetle tavsiye edilir.
Asıl konuya geçmeden önce, biraz Ağ Adresleri - IP Adresi hakkında konuşalım.
IP ana bilgisayar adresi veya daha genel olarak yalnızca IP adresi, İnternet'e bağlı ana bilgisayarları tanımlamak için kullanılır. IP, İnternet Protokolü anlamına gelir ve İnternetin genel ağ mimarisinin İnternet Katmanı anlamına gelir.
IP adresi, dört adet 8 bitlik sayı veya sekizli olarak yorumlanan 32 bitlik bir miktardır. Her IP adresi, katılan kullanıcı ağını, ağdaki ana bilgisayarı ve kullanıcı ağının sınıfını benzersiz bir şekilde tanımlar.
Bir IP adresi genellikle N1.N2.N3.N4 biçiminde noktalı ondalık gösterimle yazılır; burada her Ni, 0 ile 255 arasında ondalık bir sayıdır (00 ila FF onaltılık).
Adres Sınıfları
IP adresleri, İnternet Tahsisli Sayılar Otoritesi (IANA) tarafından yönetilir ve oluşturulur . Beş farklı adres sınıfı vardır. IP adresinin ilk dört bitini inceleyerek bir IP adresinin hangi sınıfta olduğunu belirleyebilirsiniz.
Class A adresler ile başlar 0xxxveya 1 to 126 ondalık.
Class B adresler ile başlar 10xxveya 128 to 191 ondalık.
Class C adresler ile başlar 110xveya 192 to 223 ondalık.
Class D adresler ile başlar 1110veya 224 to 239 ondalık.
Class E adresler ile başlar 1111veya 240 to 254 ondalık.
İle başlayan adresler 01111111veya 127 ondalık, geri döngü ve yerel bir makinede dahili test için ayrılmıştır [Bunu test edebilirsiniz: her zaman ping yapabilmelisiniz 127.0.0.1, kendinizi gösterir]; D Sınıfı adresler çok noktaya yayın için ayrılmıştır; E Sınıfı adresler ileride kullanılmak üzere ayrılmıştır. Ana bilgisayar adresleri için kullanılmamalıdırlar.
Misal
Class | Leftmost bits | Start address | Finish address |
Bir | 0xxx | 0.0.0.0 | 127.255.255.255 |
B | 10xx | 128.0.0.0 | 191.255.255.255 |
C | 110x | 192.0.0.0 | 223.255.255.255 |
D | 1110 | 224.0.0.0 | 239.255.255.255 |
E | 1111 | 240.0.0.0 | 255.255.255.255 |
Alt ağ oluşturma
Alt ağ oluşturma veya alt ağ oluşturma, temelde bir ağdan ayrılmak anlamına gelir. Bir kuruluştaki ağ, farklı fiziksel ortamların kullanımı (Ethernet, FDDI, WAN, vb.), Adres alanının korunması ve güvenlik gibi çeşitli nedenlerle yapılabilir. En yaygın neden ağ trafiğini kontrol etmektir.
Alt ağ oluşturmadaki temel fikir, IP adresinin ana bilgisayar tanımlayıcı bölümünü iki bölüme ayırmaktır -
- Ağ adresinin kendi içindeki bir alt ağ adresi; ve
- Alt ağdaki bir ana bilgisayar adresi.
Örneğin, yaygın bir B Sınıfı adres biçimi N1.N2.SH'dir; burada N1.N2, Sınıf B ağını tanımlar, 8 bitlik S alanı alt ağı tanımlar ve 8 bitlik H alanı, alt ağdaki ana bilgisayarı tanımlar.
Sayı açısından ana bilgisayar adlarını hatırlamak zordur ve bu nedenle Takshila veya Nalanda gibi sıradan adlarla anılırlar. Belirli bir isme karşılık gelen noktalı IP adresini bulmak için yazılım uygulamaları yazıyoruz.
Verilen alfasayısal ana bilgisayar adına göre noktalı IP adresini bulma işlemi, hostname resolution.
Bir ana bilgisayar adı çözümlemesi, yüksek kapasiteli sistemlerde bulunan özel bir yazılım tarafından yapılır. Bu sistemler, IP adreslerinin ve bunlara karşılık gelen sıradan adların eşlemesini tutan Alan Adı Sistemleri (DNS) olarak adlandırılır.
/ Etc / hosts Dosyası
Bilgisayar adları ve IP adresleri arasındaki uyuşma, dosya adı verilen korunur ana . Sistemlerin çoğunda bu dosya şurada bulunur:/etc dizin.
Bu dosyadaki girişler aşağıdaki gibi görünür -
# This represents a comments in /etc/hosts file.
127.0.0.1 localhost
192.217.44.207 nalanda metro
153.110.31.18 netserve
153.110.31.19 mainserver centeral
153.110.31.20 samsonite
64.202.167.10 ns3.secureserver.net
64.202.167.97 ns4.secureserver.net
66.249.89.104 www.google.com
68.178.157.132 services.amrood.com
Belirli bir IP adresiyle birden fazla adın ilişkilendirilebileceğini unutmayın. Bu dosya, IP adresinden ana bilgisayar adına ve tersi şekilde dönüştürülürken kullanılır.
Bu dosyayı düzenlemek için erişiminiz olmayacak, bu nedenle IP adresiyle birlikte herhangi bir ana bilgisayar adı eklemek istiyorsanız, o zaman kök iznine sahip olmanız gerekir.
Net Uygulamalarının çoğu, bazı bilgileri değiş tokuş etmek için birbirleriyle iletişim kuran iki işlemi veya iki uygulamayı ifade eden İstemci-Sunucu mimarisini kullanır. İki işlemden biri bir istemci işlemi olarak hareket eder ve diğer bir işlem bir sunucu görevi görür.
Müşteri Süreci
Bu, genellikle bilgi talebinde bulunan süreçtir. Yanıtı aldıktan sonra bu süreç sona erebilir veya başka işlemler yapabilir.
Exampleİnternet Tarayıcısı, bir HTML web sayfası almak için Web Sunucusuna bir istek gönderen bir istemci uygulaması olarak çalışır.
Sunucu İşlemi
Bu, istemcilerden talep alan süreçtir. Müşteriden bir talep aldıktan sonra, bu işlem gerekli işlemi gerçekleştirecek, istenen bilgileri toplayacak ve talep eden müşteriye gönderecektir. Tamamlandığında, başka bir müşteriye hizmet vermeye hazır hale gelir. Sunucu süreçleri her zaman tetiktedir ve gelen talepleri karşılamaya hazırdır.
Example - Web Sunucusu İnternet Tarayıcılarından gelen istekleri beklemeye devam eder ve bir tarayıcıdan herhangi bir istek alır almaz, istenen bir HTML sayfasını alır ve o Tarayıcıya geri gönderir.
İstemcinin sunucunun adresini bilmesi gerektiğini, ancak sunucunun bağlantı kurulmadan önce istemcinin adresini veya hatta varlığını bilmesi gerekmediğini unutmayın. Bir bağlantı kurulduğunda, her iki taraf da bilgi gönderip alabilir.
2 katmanlı ve 3 katmanlı mimariler
İki tür istemci-sunucu mimarisi vardır -
2-tier architecture- Bu mimaride istemci, sunucu ile doğrudan etkileşime girer. Bu tür mimarinin bazı güvenlik açıkları ve performans sorunları olabilir. Internet Explorer ve Web Sunucusu iki katmanlı mimari üzerinde çalışır. Burada güvenlik sorunları Secure Socket Layer (SSL) kullanılarak çözülür.
3-tier architectures- Bu mimaride, istemci ile sunucu arasında bir yazılım daha bulunur. Bu ara yazılıma 'ara yazılım' denir. Middleware, ağır yük durumunda tüm güvenlik kontrollerini ve yük dengelemeyi gerçekleştirmek için kullanılır. Bir ara yazılım, istemciden gelen tüm istekleri alır ve gerekli kimlik doğrulamasını yaptıktan sonra bu isteği sunucuya iletir. Daha sonra sunucu gerekli işlemi yapar ve yanıtı ara yazılıma geri gönderir ve son olarak ara yazılım bu yanıtı istemciye iletir. 3 katmanlı bir mimari uygulamak istiyorsanız, Web Logic veya WebSphere yazılımı gibi herhangi bir ara yazılımı Web Sunucunuz ile Web Tarayıcınız arasında tutabilirsiniz.
Sunucu Türleri
Sahip olabileceğiniz iki tür sunucu vardır -
Iterative Server- Bu, bir sunucu işleminin bir istemciye hizmet verdiği ve ilk isteği tamamladıktan sonra başka bir istemciden talep aldığı en basit sunucu biçimidir. Bu sırada başka bir müşteri beklemeye devam eder.
Concurrent Servers- Bir işlem daha uzun sürebilir ve başka bir istemci bu kadar uzun süre bekleyemeyeceğinden, bu tür bir sunucu aynı anda birçok isteğe hizmet vermek için birden çok eşzamanlı işlem çalıştırır. Unix altında eşzamanlı bir sunucu yazmanın en basit yolu, her istemciyi ayrı ayrı ele almak için bir çocuk süreci çatallamaktır .
Müşteri Nasıl Yapılır
Bir bağlantı kurmaya yönelik sistem çağrıları, istemci ve sunucu için biraz farklıdır, ancak her ikisi de bir soketin temel yapısını içerir. Her iki işlem de kendi soketlerini oluşturur.
İstemci tarafında bir soket oluşturmanın adımları aşağıdaki gibidir -
İle bir soket oluşturun socket() sistem çağrısı.
Soketi kullanarak sunucunun adresine bağlayın. connect() sistem çağrısı.
Veri gönderin ve alın. Bunu yapmanın birkaç yolu vardır, ancak en basit yolu,read() ve write() sistem çağrıları.
Sunucu nasıl yapılır
Sunucu tarafında bir soket oluşturmanın adımları aşağıdaki gibidir -
İle bir soket oluşturun socket() sistem çağrısı.
Soketi kullanarak bir adrese bağlayın. bind()sistem çağrısı. İnternetteki bir sunucu soketi için, bir adres, ana makinedeki bir bağlantı noktası numarasından oluşur.
İle bağlantıları dinleyin listen() sistem çağrısı.
İle bir bağlantıyı kabul edin accept()sistem çağrısı. Bu çağrı genellikle bir istemci sunucuya bağlanana kadar bağlantıyı engeller.
Kullanarak veri gönderin ve alın read() ve write() sistem çağrıları.
İstemci ve Sunucu Etkileşimi
Tam İstemci ve Sunucu etkileşimini gösteren şema aşağıdadır -
Unix Soket Programlamada adres ve bağlantı noktası hakkındaki bilgileri ve diğer bilgileri tutmak için çeşitli yapılar kullanılır. Çoğu soket işlevi, argüman olarak bir soket adres yapısına bir işaretçi gerektirir. Bu bölümde tanımlanan yapılar İnternet Protokol Ailesi ile ilgilidir.
Sockaddr
İlk yapı soket bilgilerini tutan sockaddr'dir -
struct sockaddr {
unsigned short sa_family;
char sa_data[14];
};
Bu, soket işlevi çağrılarının çoğunda geçirilecek olan genel bir soket adres yapısıdır. Aşağıdaki tablo, üye alanlarının açıklamasını sağlar -
Öznitelik | Değerler | Açıklama |
---|---|---|
sa_family | AF_INET AF_UNIX AF_NS AF_IMPLINK |
Bir adres ailesini temsil eder. İnternet tabanlı uygulamaların çoğunda AF_INET kullanıyoruz. |
sa_data | Protokole özgü Adres | 14 baytlık protokole özgü adresin içeriği, adres tipine göre yorumlanır. İnternet ailesi için, aşağıda tanımlanan sockaddr_in yapısı ile temsil edilen port numarası IP adresini kullanacağız . |
Sockaddr içinde
Soketin elemanlarına referans vermenize yardımcı olan ikinci yapı aşağıdaki gibidir -
struct sockaddr_in {
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
Üye alanlarının açıklaması aşağıdadır -
Öznitelik | Değerler | Açıklama |
---|---|---|
sa_family | AF_INET AF_UNIX AF_NS AF_IMPLINK |
Bir adres ailesini temsil eder. İnternet tabanlı uygulamaların çoğunda AF_INET kullanıyoruz. |
sin_port | Servis Portu | Ağ Bayt Sırasında 16 bitlik bir bağlantı noktası numarası. |
sin_addr | IP adresi | Ağ Bayt Sırasında 32 bitlik bir IP adresi. |
sin_zero | Kullanılmamış | Bu kullanılmadığından bu değeri NULL olarak ayarlarsınız. |
adresinde
Bu yapı sadece yukarıdaki yapıda bir yapı alanı olarak kullanılır ve 32 bit netid / hostid tutar.
struct in_addr {
unsigned long s_addr;
};
Üye alanlarının açıklaması aşağıdadır -
Öznitelik | Değerler | Açıklama |
---|---|---|
s_addr | servis bağlantı noktası | Ağ Bayt Sırasında 32 bitlik bir IP adresi. |
ev sahibi
Bu yapı, ana bilgisayarla ilgili bilgileri tutmak için kullanılır.
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]
};
Üye alanlarının açıklaması aşağıdadır -
Öznitelik | Değerler | Açıklama |
---|---|---|
h_name | ti.com vb. | Ev sahibinin resmi adıdır. Örneğin, tutorialspoint.com, google.com vb. |
h_aliases | TI | Ana bilgisayar adı takma adlarının bir listesini tutar. |
h_addrtype | AF_INET | Adres ailesini içerir ve İnternet tabanlı uygulama durumunda her zaman AF_INET olacaktır. |
h_length | 4 | İnternet Adresi için 4 olan IP adresinin uzunluğunu tutar. |
h_addr_list | in_addr | İnternet adresleri için, h_addr_list [0], h_addr_list [1] ve benzeri işaretçiler dizisi in_addr yapısının işaretleridir. |
NOTE - h_addr, geriye dönük uyumluluğu korumak için h_addr_list [0] olarak tanımlanır.
hizmetçi
Bu özel yapı, hizmet ve ilgili bağlantı noktaları ile ilgili bilgileri tutmak için kullanılır.
struct servent {
char *s_name;
char **s_aliases;
int s_port;
char *s_proto;
};
Üye alanlarının açıklaması aşağıdadır -
Öznitelik | Değerler | Açıklama |
---|---|---|
adı | http | Bu, hizmetin resmi adıdır. Örneğin, SMTP, FTP POP3 vb. |
s_aliases | ALIAS | Hizmet takma adlarının listesini tutar. Çoğu zaman bu NULL olarak ayarlanacaktır. |
spor | 80 | İlişkili bağlantı noktası numarasına sahip olacaktır. Örneğin, HTTP için bu 80 olacaktır. |
s_proto | TCP UDP |
Kullanılan protokole ayarlanmıştır. İnternet hizmetleri, TCP veya UDP kullanılarak sağlanır. |
Soket Yapılarıyla İlgili İpuçları
Soket adres yapıları, her ağ programının ayrılmaz bir parçasıdır. Onları tahsis ediyoruz, dolduruyoruz ve çeşitli soket işlevlerine işaretçiler gönderiyoruz. Bazen bu yapılardan birine bir soket işlevine bir işaretçi aktarırız ve bu, içeriği doldurur.
Bu yapıları her zaman referans olarak iletiriz (yani, yapının kendisine değil, yapıya bir işaretçi göndeririz) ve her zaman yapının boyutunu başka bir argüman olarak iletiriz.
Bir soket işlevi bir yapıyı doldurduğunda, uzunluk da referans olarak iletilir, böylece değeri işlev tarafından güncellenebilir. Bunlara değer-sonuç argümanları diyoruz.
Her zaman, bzero () işlevleri için memset () kullanarak yapı değişkenlerini NULL (yani '\ 0') olarak ayarlayın, aksi takdirde yapınızda beklenmedik önemsiz değerler alabilir.
Bir istemci işlemi bir sunucuya bağlanmak istediğinde, istemcinin bağlanmak istediği sunucuyu tanımlamanın bir yolu olmalıdır. İstemci, sunucunun bulunduğu ana bilgisayarın 32 bit İnternet adresini biliyorsa, bu ana bilgisayarla iletişim kurabilir. Ancak istemci, o ana bilgisayarda çalışan belirli sunucu sürecini nasıl tanımlar?
Bir ana bilgisayarda çalışan belirli bir sunucu işlemini tanımlama sorununu çözmek için, hem TCP hem de UDP iyi bilinen bir bağlantı noktası grubu tanımlamıştır.
Amacımız için, bir bağlantı noktası 1024 ile 65535 arasında bir tam sayı olarak tanımlanacaktır. Bunun nedeni, 1024'ten küçük tüm bağlantı noktası numaralarının iyi bilinen kabul edilmesidir - örneğin, telnet bağlantı noktası 23'ü, http 80'i, ftp 21'i ve bunun gibi.
Ağ hizmetlerine bağlantı noktası atamaları / etc / services dosyasında bulunabilir. Kendi sunucunuzu yazıyorsanız, sunucunuza bir bağlantı noktası atamak için özen gösterilmelidir. Bu bağlantı noktasının başka bir sunucuya atanmaması gerektiğinden emin olmalısınız.
Normalde herhangi bir port numarasını 5000'den fazla atamak bir uygulamadır. Ancak 5000'den fazla port numarasına sahip sunucuları yazan birçok kuruluş vardır. Örneğin, Yahoo Messenger 5050'de, SIP Sunucusu 5060'ta vb.
Örnek Bağlantı Noktaları ve Hizmetler
İşte küçük bir hizmet listesi ve ilgili bağlantı noktaları. İnternet bağlantı noktalarının ve ilgili hizmetin en güncel listesini IANA - TCP / IP Bağlantı Noktası Atamalarında bulabilirsiniz .
Service | Port Number | Service Description |
Eko | 7 | UDP / TCP aldığını geri gönderir. |
atmak | 9 | UDP / TCP girişi atar. |
gündüz | 13 | UDP / TCP, ASCII zamanını döndürür. |
Chargen | 19 | UDP / TCP karakterleri döndürür. |
ftp | 21 | TCP dosya aktarımı. |
telnet | 23 | TCP uzaktan oturum açma. |
smtp | 25 | TCP e-postası. |
gündüz | 37 | UDP / TCP, ikili zamanı döndürür. |
tftp | 69 | UDP önemsiz dosya aktarımı. |
parmak | 79 | Kullanıcılar hakkında TCP bilgisi. |
http | 80 | TCP World Wide Web. |
oturum aç | 513 | TCP uzaktan oturum açma. |
DSÖ | 513 | Kullanıcılar hakkında UDP farklı bilgiler. |
Xserver | 6000 | TCP X pencereleri (NB> 1023). |
Liman ve Servis Fonksiyonları
Unix, hizmet adını / etc / services dosyasından almak için aşağıdaki işlevleri sağlar.
struct servent *getservbyname(char *name, char *proto) - Bu çağrı, hizmet adını ve protokol adını alır ve o hizmet için ilgili bağlantı noktası numarasını döndürür.
struct servent *getservbyport(int port, char *proto) - Bu çağrı, bağlantı noktası numarasını ve protokol adını alır ve ilgili hizmet adını döndürür.
Her işlevin dönüş değeri, aşağıdaki biçime sahip bir yapıya göstericidir -
struct servent {
char *s_name;
char **s_aliases;
int s_port;
char *s_proto;
};
Üye alanlarının açıklaması aşağıdadır -
Öznitelik | Değerler | Açıklama |
---|---|---|
adı | http | Hizmetin resmi adıdır. Örneğin, SMTP, FTP POP3 vb. |
s_aliases | ALIAS | Hizmet takma adlarının listesini tutar. Çoğu zaman NULL olarak ayarlanacaktır. |
spor | 80 | İlişkili bağlantı noktası numarasına sahip olacaktır. Örneğin, HTTP için 80 olacaktır. |
s_proto | TCP UDP |
Kullanılan protokole ayarlanmıştır. İnternet hizmetleri, TCP veya UDP kullanılarak sağlanır. |
Maalesef, tüm bilgisayarlar çok baytlı bir değer içeren baytları aynı sırada depolamaz. 2 bayttan oluşan 16 bitlik bir internet düşünün. Bu değeri saklamanın iki yolu vardır.
Little Endian - Bu şemada, düşük değerli bayt başlangıç adresinde (A) ve yüksek sıralı bayt sonraki adreste (A + 1) saklanır.
Big Endian - Bu şemada, yüksek dereceli bayt başlangıç adresinde (A) saklanır ve düşük sıralı bayt bir sonraki adreste (A + 1) saklanır.
Farklı bayt sırası kurallarına sahip makinelerin birbirleriyle iletişim kurmasına izin vermek için İnternet protokolleri, ağ üzerinden iletilen veriler için kanonik bir bayt sırası kuralı belirler. Bu, Ağ Bayt Sırası olarak bilinir.
İnternet soket bağlantısı kurarken, sockaddr_in yapısının sin_port ve sin_addr üyelerindeki verilerin Ağ Bayt Sırasında temsil edildiğinden emin olmalısınız.
Bayt Sıralama İşlevleri
Bir ana bilgisayarın dahili gösterimi ile Ağ Bayt Sırası arasında veri dönüştürme rutinleri aşağıdaki gibidir -
Fonksiyon | Açıklama |
---|---|
htons () | Host to Network Short |
htonl () | Ağda Uzun |
ntohl () | Uzun Barındıracak Ağ |
ntohs () | Kısa Barındırma Ağı |
Aşağıda bu işlevler hakkında biraz daha ayrıntı listelenmiştir -
unsigned short htons(unsigned short hostshort) - Bu işlev 16 bitlik (2 bayt) miktarları ana bilgisayar bayt sırasından ağ bayt sırasına dönüştürür.
unsigned long htonl(unsigned long hostlong) - Bu işlev 32 bitlik (4 bayt) miktarları ana bilgisayar bayt sırasından ağ bayt sırasına dönüştürür.
unsigned short ntohs(unsigned short netshort) - Bu işlev 16 bitlik (2 bayt) miktarları ağ bayt sırasından ana bilgisayar bayt sırasına dönüştürür.
unsigned long ntohl(unsigned long netlong) - Bu işlev, 32 bitlik miktarları ağ bayt sırasından ana bilgisayar bayt sırasına dönüştürür.
Bu işlevler makrolardır ve dönüştürme kaynak kodunun çağıran programa eklenmesiyle sonuçlanır. Küçük endian makinelerde kod, değerleri ağ bayt sırasına göre değiştirecektir. Big-endian makinelerde, gerekli olmadığı için kod girilmez; işlevler boş olarak tanımlanır.
Ana Bilgisayar Bayt Sırasını Belirleme Programı
Aşağıdaki kodu bir byteorder.c dosyasında saklayın ve ardından onu derleyin ve makinenizde çalıştırın.
Bu örnekte, iki baytlık değeri 0x0102'yi kısa tamsayıda saklıyoruz ve ardından baytı belirlemek için ardışık iki bayta, c [0] (A adresi) ve c [1] (A + 1 adresi) sipariş.
#include <stdio.h>
int main(int argc, char **argv) {
union {
short s;
char c[sizeof(short)];
}un;
un.s = 0x0102;
if (sizeof(short) == 2) {
if (un.c[0] == 1 && un.c[1] == 2)
printf("big-endian\n");
else if (un.c[0] == 2 && un.c[1] == 1)
printf("little-endian\n");
else
printf("unknown\n");
}
else {
printf("sizeof(short) = %d\n", sizeof(short));
}
exit(0);
}
Bu program tarafından bir Pentium makinesinde üretilen bir çıktı aşağıdaki gibidir -
$> gcc byteorder.c $> ./a.out
little-endian
$>
Unix, IP adreslerini değiştirmenize yardımcı olmak için çeşitli işlev çağrıları sağlar. Bu işlevler, İnternet adreslerini ASCII dizeleri (insanların kullanmayı tercih ettikleri) ile ağ bayt sıralı ikili değerler (soket adres yapılarında saklanan değerler) arasında dönüştürür.
IPv4 adresleme için aşağıdaki üç işlev çağrısı kullanılır -
- int inet_aton (const char * strptr, struct in_addr * addrptr)
- in_addr_t inet_addr (const char * strptr)
- char * inet_ntoa (struct in_addr inaddr)
int inet_aton (const char * strptr, struct in_addr * addrptr)
Bu işlev çağrısı, İnternet standart nokta gösteriminde belirtilen dizeyi bir ağ adresine dönüştürür ve adresi sağlanan yapıda depolar. Dönüştürülen adres Ağ Bayt Sırasına göre (soldan sağa sıralanan baytlar) olacaktır. Dize geçerliyse 1, hata durumunda 0 döndürür.
Kullanım örneği aşağıdadır -
#include <arpa/inet.h>
(...)
int retval;
struct in_addr addrptr
memset(&addrptr, '\0', sizeof(addrptr));
retval = inet_aton("68.178.157.132", &addrptr);
(...)
in_addr_t inet_addr (const char * strptr)
Bu işlev çağrısı, İnternet standart nokta gösteriminde belirtilen dizeyi İnternet adresi olarak kullanılmaya uygun bir tamsayı değerine dönüştürür. Dönüştürülen adres Ağ Bayt Sırasına göre (soldan sağa sıralanan baytlar) olacaktır. 32 bitlik ikili ağ baytı sıralı IPv4 adresi ve hata durumunda INADDR_NONE döndürür.
Kullanım örneği aşağıdadır -
#include <arpa/inet.h>
(...)
struct sockaddr_in dest;
memset(&dest, '\0', sizeof(dest));
dest.sin_addr.s_addr = inet_addr("68.178.157.132");
(...)
char * inet_ntoa (struct in_addr inaddr)
Bu işlev çağrısı, belirtilen ana bilgisayar adresini İnternet standardı nokta gösterimindeki bir dizeye dönüştürür.
Kullanım örneği aşağıdadır -
#include <arpa/inet.h>
(...)
char *ip;
ip = inet_ntoa(dest.sin_addr);
printf("IP Address is: %s\n",ip);
(...)
Bu bölüm, eksiksiz bir TCP istemcisi ve sunucusu yazmak için gereken temel yuva işlevlerini açıklar.
Aşağıdaki şema, tam İstemci ve Sunucu etkileşimini göstermektedir -
Soket İşlevi
Ağ G / Ç'yi gerçekleştirmek için, bir işlemin yapması gereken ilk şey, soket işlevini çağırmak, istenen iletişim protokolü türünü ve protokol ailesini vb. Belirtmektir.
#include <sys/types.h>
#include <sys/socket.h>
int socket (int family, int type, int protocol);
Bu çağrı, sonraki sistem çağrılarında veya hata durumunda -1 kullanabileceğiniz bir soket tanımlayıcısı döndürür.
Parametreler
family - Protokol ailesini belirtir ve aşağıda gösterilen sabitlerden biridir -
Aile | Açıklama |
---|---|
AF_INET | IPv4 protokolleri |
AF_INET6 | IPv6 protokolleri |
AF_LOCAL | Unix alan protokolleri |
AF_ROUTE | Yönlendirme Soketleri |
AF_KEY | Ket soketi |
Bu bölüm IPv4 dışındaki diğer protokolleri kapsamaz.
type- İstediğiniz soket türünü belirtir. Aşağıdaki değerlerden birini alabilir -
Tür | Açıklama |
---|---|
SOCK_STREAM | Akış soketi |
SOCK_DGRAM | Datagram soketi |
SOCK_SEQPACKET | Sıralı paket soketi |
SOCK_RAW | Ham soket |
protocol - Bağımsız değişken, aşağıda verilen belirli protokol türüne veya belirli aile ve tür birleşimi için sistemin varsayılanını seçmek için 0'a ayarlanmalıdır -
Protokol | Açıklama |
---|---|
IPPROTO_TCP | TCP aktarım protokolü |
IPPROTO_UDP | UDP taşıma protokolü |
IPPROTO_SCTP | SCTP taşıma protokolü |
bağlantı Fonksiyonu
Connect işlevi, bir TCP sunucusu ile bağlantı kurmak için TCP istemci tarafından kullanılır.
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
Bu çağrı, sunucuya başarılı bir şekilde bağlanırsa 0 döndürür, aksi takdirde hata durumunda -1 döndürür.
Parametreler
sockfd - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
serv_addr - Hedef IP adresini ve bağlantı noktasını içeren sockaddr yapısına bir göstericidir.
addrlen - Sizeof (struct sockaddr) olarak ayarlayın.
bağlama İşlevi
Bağlama işlevi, bir sokete yerel protokol adresini atar. İnternet protokollerinde, protokol adresi, 16 bitlik bir TCP veya UDP bağlantı noktası numarasıyla birlikte 32 bit IPv4 adresi veya 128 bit IPv6 adresinin birleşimidir. Bu işlev yalnızca TCP sunucusu tarafından çağrılır.
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *my_addr,int addrlen);
Bu çağrı, adrese başarılı bir şekilde bağlanırsa 0 döndürür, aksi takdirde hata durumunda -1 döndürür.
Parametreler
sockfd - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
my_addr - Yerel IP adresini ve bağlantı noktasını içeren sockaddr yapısının bir göstericisidir.
addrlen - Sizeof (struct sockaddr) olarak ayarlayın.
IP adresinizi ve bağlantı noktanızı otomatik olarak girebilirsiniz
Bağlantı noktası numarası için 0 değeri, sistemin rastgele bir bağlantı noktası seçeceği anlamına gelir ve IP adresi için INADDR_ANY değeri, sunucunun IP adresinin otomatik olarak atanacağı anlamına gelir.
server.sin_port = 0;
server.sin_addr.s_addr = INADDR_ANY;
NOTE- 1024'ün altındaki tüm bağlantı noktaları ayrılmıştır. Diğer programlar tarafından kullanılmıyorsa, 1024'ün üzerinde ve 65535'in altında bir bağlantı noktası ayarlayabilirsiniz.
dinle İşlevini
Dinlemek işlevi yalnızca TCP sunucusu tarafından denir ve iki eylemleri gerçekleştirir edilir -
Listen işlevi, bağlantısız bir soketi pasif bir sokete dönüştürerek çekirdeğin bu sokete yönlendirilen gelen bağlantı isteklerini kabul etmesi gerektiğini belirtir.
Bu işlevin ikinci argümanı, çekirdeğin bu yuva için sıraya koyması gereken maksimum bağlantı sayısını belirtir.
#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd,int backlog);
Bu çağrı, başarı durumunda 0 döndürür, aksi takdirde hata durumunda -1 döndürür.
Parametreler
sockfd - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
backlog - İzin verilen bağlantı sayısıdır.
kabul İşlevini
Kabul işlevi tamamlanmış bağlantı sıranın önünden sonraki tamamlanmış bağlantıyı dönmek için bir TCP sunucu tarafından çağrılır. Aramanın imzası aşağıdaki gibidir -
#include <sys/types.h>
#include <sys/socket.h>
int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
Bu çağrı, başarı durumunda negatif olmayan bir tanımlayıcı döndürür, aksi takdirde hata durumunda -1 döndürür. Döndürülen tanımlayıcının bir istemci soket tanımlayıcısı olduğu varsayılır ve istemci ile iletişim kurmak için tüm okuma-yazma işlemleri bu tanımlayıcı üzerinde yapılacaktır.
Parametreler
sockfd - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
cliaddr - İstemci IP adresini ve bağlantı noktasını içeren sockaddr yapısına bir göstericidir.
addrlen - Sizeof (struct sockaddr) olarak ayarlayın.
gönderme Fonksiyonu
Gönderme işlevi akış soketi veya BAĞLANTILI veri yuva üzerinden veri göndermek için kullanılır. BAĞLANTISIZ datagram soketleri üzerinden veri göndermek istiyorsanız, sendto () işlevini kullanmalısınız.
Veri göndermek için write () sistem çağrısını kullanabilirsiniz. İmzası aşağıdaki gibidir -
int send(int sockfd, const void *msg, int len, int flags);
Bu çağrı, gönderilen bayt sayısını döndürür, aksi takdirde hata durumunda -1 döndürür.
Parametreler
sockfd - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
msg - Göndermek istediğiniz verilere bir göstericidir.
len - Göndermek istediğiniz verinin uzunluğudur (bayt cinsinden).
flags - 0 olarak ayarlanmıştır.
recv İşlevi
Recv işlevi, akım priz veya BAĞLI veri yuva üzerinden veri almak için kullanılır. BAĞLANTISIZ datagram soketleri üzerinden veri almak istiyorsanız recvfrom () kullanmalısınız.
Verileri okumak için read () sistem çağrısını kullanabilirsiniz. Bu çağrı, yardımcı işlevler bölümünde açıklanmıştır.
int recv(int sockfd, void *buf, int len, unsigned int flags);
Bu çağrı, arabelleğe okunan bayt sayısını döndürür, aksi takdirde hata durumunda -1 döndürür.
Parametreler
sockfd - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
buf - Bilginin okunacağı ara bellektir.
len - Tamponun maksimum uzunluğudur.
flags - 0 olarak ayarlanmıştır.
sento İşlevi
Sento işlevi bağlantısız veri yuva üzerinden veri göndermek için kullanılır. İmzası aşağıdaki gibidir -
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
Bu çağrı, gönderilen bayt sayısını döndürür, aksi takdirde hata durumunda -1 döndürür.
Parametreler
sockfd - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
msg - Göndermek istediğiniz verilere bir göstericidir.
len - Göndermek istediğiniz verinin uzunluğudur (bayt cinsinden).
flags - 0 olarak ayarlanmıştır.
to - Verilerin gönderilmesi gereken ana bilgisayar için sockaddr yapılandırmak için bir göstericidir.
tolen - Sizeof (struct sockaddr) olarak ayarlanır.
recvfrom İşlevi
Recvfrom fonksiyonu bağlı olmayan veri yuva veri almak için kullanılır.
int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);
Bu çağrı, arabelleğe okunan bayt sayısını döndürür, aksi takdirde hata durumunda -1 döndürür.
Parametreler
sockfd - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
buf - Bilginin okunacağı ara bellektir.
len - Tamponun maksimum uzunluğudur.
flags - 0 olarak ayarlanmıştır.
from - Verilerin okunması gereken ana bilgisayar için sockaddr yapılandırmak için bir göstericidir.
fromlen - Sizeof (struct sockaddr) olarak ayarlanır.
yakın İşlevi
Yakın fonksiyon istemci ve sunucu arasındaki iletişimi kapatmak için kullanılır. Sözdizimi aşağıdaki gibidir -
int close( int sockfd );
Bu çağrı, başarı durumunda 0 döndürür, aksi takdirde hata durumunda -1 döndürür.
Parametreler
sockfd - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
kapatma Fonksiyonu
Kapatma işlevi incelikle istemci ve sunucu arasındaki iletişim kapatmak için kullanılır. Bu işlev, kapatma işlevine kıyasla daha fazla kontrol sağlar. Aşağıda, kapatma sözdizimi verilmiştir -
int shutdown(int sockfd, int how);
Bu çağrı, başarı durumunda 0 döndürür, aksi takdirde hata durumunda -1 döndürür.
Parametreler
sockfd - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
how - Rakamlardan birini yazın -
0 - almaya izin verilmediğini gösterir,
1 - göndermeye izin verilmediğini ve
2- hem göndermeye hem de almaya izin verilmediğini gösterir. Ne zaman nasıl 2 olarak ayarlandığında, bu yakın olarak aynı şey ().
seçme İşlevi
Seçme fonksiyonu yazma, okuma için hazır hazır, veya beklemede bir hata durumunda, belirtilen dosya tanımlayıcıları ettiğini gösterir.
Bir uygulama recv veya recvfrom çağırdığında , bu sokete veri gelene kadar engellenir. Bir uygulama, gelen veri akışı boşken başka yararlı işlemler yapıyor olabilir. Diğer bir durum, bir uygulamanın birden çok soketten veri almasıdır.
Arayan recv veya recvfrom onun giriş kuyruğu önler diğer yuvalarından veri acil resepsiyon veri yok bir soket üzerinde. Select işlev çağrısı, programın tüm soket tutamaçlarını engellemeyen okuma ve yazma işlemleri için uygun olup olmadıklarını görmek için sorgulamasına izin vererek bu sorunu çözer.
Aşağıda Verilen yazılış biçimi seçin -
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
Bu çağrı, başarı durumunda 0 döndürür, aksi takdirde hata durumunda -1 döndürür.
Parametreler
nfds- Test edilecek dosya tanımlayıcılarının aralığını belirtir. Select () işlevi, 0 ila nfds-1 aralığındaki dosya tanımlayıcılarını test eder.
readfds- Girişte okunmaya hazır olup olmadığı kontrol edilecek dosya tanımlayıcılarını ve çıktıda hangi dosya tanımlayıcılarının okumaya hazır olduğunu belirten fd_set türünde bir nesneye işaret eder. Boş bir küme belirtmek için NULL olabilir.
writefds- Girdi üzerinde, yazmaya hazır olup olmadığı kontrol edilecek dosya tanımlayıcılarını ve çıktıda hangi dosya tanımlayıcılarının yazmaya hazır olduğunu belirten fd_set türünde bir nesneye işaret eder. Boş bir küme belirtmek için NULL olabilir.
exceptfds- Girdi üzerinde, bekleyen hata durumları için kontrol edilecek dosya tanımlayıcılarını belirten fd_set türünde bir nesneye işaret eder ve çıktıda, hangi dosya tanımlayıcılarının bekleyen hata koşullarının olduğunu belirtir. Boş bir küme belirtmek için NULL olabilir.
timeout- Select çağrısının, kullanılabilir bir G / Ç işlemi için tanımlayıcıları ne kadar süreyle yoklaması gerektiğini belirten bir timeval yapısına işaret eder. Zaman aşımı değeri 0 ise, seçim hemen dönecektir. Zaman aşımı bağımsız değişkeni NULL ise, en az bir dosya / soket tutamacı kullanılabilir bir G / Ç işlemi için hazır olana kadar seçim engellenecektir. Aksi takdirde , zaman aşımı süresi geçtikten sonra VEYA en az bir dosya / soket tanımlayıcısı bir G / Ç işlemi için hazır olduğunda select dönecektir.
Select'in dönüş değeri, G / Ç için hazır olan dosya tanımlayıcı kümelerinde belirtilen tutamaçların sayısıdır. Zaman aşımı alanı tarafından belirtilen süre sınırına ulaşılırsa, 0 döndür öğesini seçin. Bir dosya tanımlayıcı kümesini işlemek için aşağıdaki makrolar mevcuttur -
FD_CLR(fd, &fdset)- fdset dosya tanımlayıcı kümesindeki fd dosya tanımlayıcısının bitini temizler .
FD_ISSET(fd, &fdset)- fd dosya tanımlayıcısının biti , fdset ile gösterilen dosya tanımlayıcı kümesinde ayarlanmışsa, sıfır olmayan bir değer döndürür , aksi takdirde 0 döndürür.
FD_SET(fd, &fdset) - fdset dosya tanımlayıcı kümesindeki fd dosya tanımlayıcısının bitini ayarlar.
FD_ZERO(&fdset) - fdset dosya tanımlayıcı kümesini tüm dosya tanımlayıcıları için sıfır bit olacak şekilde başlatır.
Bu makroların davranışı, fd bağımsız değişkeni 0'dan küçükse veya FD_SETSIZE'a eşit veya ondan büyükse tanımsızdır.
Misal
fd_set fds;
struct timeval tv;
/* do socket initialization etc.
tv.tv_sec = 1;
tv.tv_usec = 500000;
/* tv now represents 1.5 seconds */
FD_ZERO(&fds);
/* adds sock to the file descriptor set */
FD_SET(sock, &fds);
/* wait 1.5 seconds for any data to be read from any single socket */
select(sock+1, &fds, NULL, NULL, &tv);
if (FD_ISSET(sock, &fds)) {
recvfrom(s, buffer, buffer_len, 0, &sa, &sa_len);
/* do something */
}
else {
/* do something else */
}
Bu bölümde, soket programlaması yapılırken kullanılan tüm yardımcı fonksiyonlar açıklanmaktadır. Diğer yardımcı işlevler bölümlerde açıklanmıştır -Ports and Servicesve Ağ Byte Orders.
yazma İşlevi
Yazma tampon yazma nbyte bayt işlev denemeleri ile işaret tampon tamponundan açık dosya tanımlayıcısı ile ilişkili dosya Fildes .
Başka bir işleme veri göndermek için send () işlevini de kullanabilirsiniz .
#include <unistd.h>
int write(int fildes, const void *buf, int nbyte);
Başarılı bir şekilde tamamlandıktan sonra write (), fildes ile ilişkilendirilmiş dosyaya fiilen yazılan bayt sayısını döndürür. Bu sayı hiçbir zaman nbayttan büyük değildir. Aksi takdirde -1 döndürülür.
Parametreler
fildes - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
buf - Göndermek istediğiniz verilere bir göstericidir.
nbyte- Yazılacak bayt sayısıdır. Eğer nbyte 0 ise, write () 0 döndürür ve dosya normal bir dosyaysa başka sonuç vermez; aksi takdirde sonuçlar belirtilmez.
okuma Fonksiyonu
Okuma tampon tampon ile işaret içine fonksiyon girişimleri, tampon, Fildes ilişkili dosyadan nbyte bayt okuyun.
Ayrıca başka bir işleme veri okumak için recv () işlevini de kullanabilirsiniz .
#include <unistd.h>
int read(int fildes, const void *buf, int nbyte);
Başarılı bir şekilde tamamlandıktan sonra write (), fildes ile ilişkilendirilmiş dosyaya fiilen yazılan bayt sayısını döndürür. Bu sayı hiçbir zaman nbayttan büyük değildir. Aksi takdirde -1 döndürülür.
Parametreler
fildes - Soket işlevi tarafından döndürülen bir soket tanımlayıcısıdır.
buf - Bilginin okunacağı ara bellektir.
nbyte - Okunacak bayt sayısıdır.
çatal İşlevi
Çatal işlevi yeni bir süreç oluşturur. Alt süreç adı verilen yeni süreç, çağıran sürecin (ana süreç) tam bir kopyası olacaktır. Alt süreç, üst süreçten birçok özniteliği miras alır.
#include <sys/types.h>
#include <unistd.h>
int fork(void);
Başarılı bir şekilde tamamlandıktan sonra fork (), alt sürece 0 ve alt sürecin süreç kimliğini de üst sürece döndürür. Aksi takdirde -1, üst sürece döndürülür, hiçbir çocuk süreç oluşturulmaz ve hatayı belirtmek için errno ayarlanır.
Parametreler
void - Parametre gerekmediği anlamına gelir.
bzero İşlevi
Bzero fonksiyon yerleri nbyte boş dize bayt s . Bu işlev, tüm soket yapılarını boş değerlerle ayarlamak için kullanılır.
void bzero(void *s, int nbyte);
Bu işlev hiçbir şey döndürmez.
Parametreler
s- Boş baytlarla doldurulması gereken dizgeyi belirtir. Bu, soket yapısı değişkenine bir nokta olacaktır.
nbyte- Boş değerlerle doldurulacak bayt sayısını belirtir. Bu, soket yapısının boyutu olacaktır.
bcmp İşlevi
Bcmp fonksiyonu bayt dize s2 karşı bayt dize s1 karşılaştırır. Her iki dizenin de nbyte bayt uzunluğunda olduğu varsayılır.
int bcmp(const void *s1, const void *s2, int nbyte);
Bu işlev, her iki dizge de aynıysa 0, aksi takdirde 1 döndürür. Bcmp () işlevi, nbyte 0 olduğunda her zaman 0 döndürür.
Parametreler
s1 - Karşılaştırılacak ilk dizgeyi belirtir.
s2 - Karşılaştırılacak ikinci dizeyi belirtir.
nbyte - Karşılaştırılacak bayt sayısını belirtir.
bcopy İşlevi
Bcopy fonksiyon kopyalar nbyte dize s2 dize s1 den bayt. Çakışan dizeler doğru şekilde işlenir.
void bcopy(const void *s1, void *s2, int nbyte);
Bu işlev hiçbir şey döndürmez.
Parametreler
s1 - Kaynak dizeyi belirtir.
s2v - Hedef dizeyi belirtir.
nbyte - Kopyalanacak bayt sayısını belirtir.
memset İşlevi
Memset fonksiyonu da aynı şekilde olarak ayarlamak yapısı değişken için kullanılanbzero. Aşağıda verilen söz dizimine bir göz atın.
void *memset(void *s, int c, int nbyte);
Bu işlev void'e bir gösterici döndürür; aslında, ayarlanmış belleğe bir işaretçi ve buna göre sınıflandırmanız gerekir.
Parametreler
s - Ayarlanacak kaynağı belirtir.
c - Nbayt yerlerinde ayarlanacak karakteri belirtir.
nbyte - Ayarlanacak bayt sayısını belirtir.
Bir işlemi bir TCP sunucusu yapmak için, aşağıda verilen adımları izlemeniz gerekir -
Soket () sistem çağrısıyla bir soket oluşturun .
Bind () sistem çağrısını kullanarak soketi bir adrese bağlayın . İnternetteki bir sunucu soketi için, bir adres, ana makinedeki bir bağlantı noktası numarasından oluşur.
Listen () sistem çağrısı ile bağlantıları dinleyin .
Accept () sistem çağrısı ile bir bağlantıyı kabul edin . Bu çağrı tipik olarak bir istemci sunucuya bağlanana kadar engeller.
Read () and write () sistem çağrılarını kullanarak veri gönderin ve alın .
Şimdi bu adımları kaynak kodu şeklinde koyalım. Bu kodu server.c dosyasına koyun ve gcc derleyicisi ile derleyin .
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here process will
* go in sleep mode and will wait for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
/* Accept actual connection from the client */
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* If connection is established then start communicating */
bzero(buffer,256);
n = read( newsockfd,buffer,255 );
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n",buffer);
/* Write a response to the client */
n = write(newsockfd,"I got your message",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
return 0;
}
Birden Fazla Bağlantıyı Yönetin
Sunucunun birden çok eşzamanlı bağlantıyı yönetmesine izin vermek için yukarıdaki kodda aşağıdaki değişiklikleri yapıyoruz -
Put kabul sonsuz döngüye tablosu ve aşağıdaki kodu.
Bir bağlantı kurulduktan sonra, yeni bir işlem oluşturmak için fork () çağırın .
Çocuk süreç sockfd'yi kapatır ve doprocessing işlevini çağırır , yeni soket dosya tanımlayıcısını argüman olarak iletir . Doprocessing () geri dönmesinin gösterdiği gibi, iki işlem konuşmalarını tamamladığında , bu işlem basitçe çıkar.
Üst süreç newsockfd'yi kapatır . Bu kodun tümü sonsuz bir döngüde olduğundan, bir sonraki bağlantıyı beklemek için accept ifadesine dönecektir.
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
Aşağıdaki kod dizisi, işleme işlevinin basit bir uygulamasını gösterir .
void doprocessing (int sock) {
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n",buffer);
n = write(sock,"I got your message",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}
Bir işlemi bir TCP istemcisi yapmak için, aşağıda verilen adımları izlemeniz gerekir & eksi;
Soket () sistem çağrısıyla bir soket oluşturun .
Soketi connect () sistem çağrısını kullanarak sunucunun adresine bağlayın .
Veri gönderin ve alın. Bunu yapmanın birkaç yolu vardır, ancak en basit yolu read () ve write () sistem çağrılarını kullanmaktır.
Şimdi bu adımları kaynak kodu şeklinde koyalım. Bu kodu dosyaya koyunclient.c ve derleyin gcc derleyici.
Bu programı çalıştırın ve başka bir Unix penceresinde çalıştırmış olmanız gereken sunucuya bağlanmak için sunucunun ana bilgisayar adını ve bağlantı noktası numarasını iletin.
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
/* Create a socket point */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
/* Now connect to the server */
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
exit(1);
}
/* Now ask for a message from the user, this message
* will be read by server
*/
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
/* Send message to the server */
n = write(sockfd, buffer, strlen(buffer));
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
/* Now read server response */
bzero(buffer,256);
n = read(sockfd, buffer, 255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("%s\n",buffer);
return 0;
}
Soket programlamayla ilgili tüm fonksiyonların listesi burada.
Liman ve Servis Fonksiyonları
Unix, hizmet adını / etc / services dosyasından almak için aşağıdaki işlevleri sağlar.
struct servent *getservbyname(char *name, char *proto) - Bu çağrı, bir hizmet adı ve bir protokol adı alır ve o hizmet için ilgili bağlantı noktası numarasını döndürür.
struct servent *getservbyport(int port, char *proto) - Bu çağrı bir port numarası ve bir protokol adı alır ve ilgili servis adını döndürür.
Bayt Sıralama İşlevleri
unsigned short htons (unsigned short hostshort) - Bu işlev 16 bitlik (2 bayt) miktarları ana bilgisayar bayt sırasından ağ bayt sırasına dönüştürür.
unsigned long htonl (unsigned long hostlong) - Bu işlev 32 bitlik (4 bayt) miktarları ana bilgisayar bayt sırasından ağ bayt sırasına dönüştürür.
unsigned short ntohs (unsigned short netshort) - Bu işlev 16 bitlik (2 bayt) miktarları ağ bayt sırasından ana bilgisayar bayt sırasına dönüştürür.
unsigned long ntohl (unsigned long netlong) - Bu işlev, 32 bitlik miktarları ağ bayt sırasından ana bilgisayar bayt sırasına dönüştürür.
IP Adresi Fonksiyonları
int inet_aton (const char *strptr, struct in_addr *addrptr)- Bu işlev çağrısı, İnternet standart nokta gösteriminde belirtilen dizeyi bir ağ adresine dönüştürür ve adresi sağlanan yapıda depolar. Dönüştürülen adres Ağ Bayt Sırasına göre (soldan sağa sıralanan baytlar) olacaktır. Dize geçerliyse 1, hata durumunda 0 döndürür.
in_addr_t inet_addr (const char *strptr)- Bu işlev çağrısı, İnternet standart nokta gösteriminde belirtilen dizeyi İnternet adresi olarak kullanılmaya uygun bir tam sayı değerine dönüştürür. Dönüştürülen adres Ağ Bayt Sırasına göre (soldan sağa sıralanan baytlar) olacaktır. 32 bitlik ikili ağ baytı sıralı IPv4 adresi ve hata durumunda INADDR_NONE döndürür.
char *inet_ntoa (struct in_addr inaddr) - Bu işlev çağrısı, belirtilen ana bilgisayar adresini İnternet standardı nokta gösterimindeki bir dizeye dönüştürür.
Soket Çekirdek Fonksiyonları
int socket (int family, int type, int protocol) - Bu çağrı, sonraki sistem çağrılarında kullanabileceğiniz bir yuva tanımlayıcısı döndürür veya hata durumunda -1 verir.
int connect (int sockfd, struct sockaddr *serv_addr, int addrlen)- Bağlan işlevi, bir TCP istemcisi tarafından bir TCP sunucusuyla bağlantı kurmak için kullanılır. Bu çağrı, sunucuya başarılı bir şekilde bağlanırsa 0 döndürür, aksi takdirde -1 döndürür.
int bind(int sockfd, struct sockaddr *my_addr,int addrlen)- Bağlama işlevi, bir sokete yerel bir protokol adresi atar. Bu çağrı, adrese başarılı bir şekilde bağlanırsa 0 döndürür, aksi takdirde -1 döndürür.
int listen(int sockfd, int backlog)- Dinleme işlevi, yalnızca bir TCP sunucusu tarafından istemci isteğini dinlemek için çağrılır. Bu çağrı, başarı durumunda 0 döndürür, aksi takdirde -1 döndürür.
int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)- Kabul işlevi, istemci isteklerini kabul etmek ve gerçek bağlantı kurmak için bir TCP sunucusu tarafından çağrılır. Bu çağrı, başarı durumunda negatif olmayan bir tanımlayıcı döndürür, aksi takdirde -1 döndürür.
int send(int sockfd, const void *msg, int len, int flags)- Gönderme işlevi, verileri akış soketleri veya BAĞLANTILI datagram soketleri üzerinden göndermek için kullanılır. Bu çağrı, gönderilen bayt sayısını döndürür, aksi takdirde -1 döndürür.
int recv (int sockfd, void *buf, int len, unsigned int flags)- Recv işlevi, veri akış soketleri veya BAĞLANTILI datagram soketleri üzerinden veri almak için kullanılır. Bu çağrı, arabelleğe okunan bayt sayısını döndürür, aksi takdirde hata durumunda -1 döndürür.
int sendto (int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen)- sendto işlevi BAĞLANTISIZ datagram soketleri üzerinden veri göndermek için kullanılır. Bu çağrı, gönderilen bayt sayısını döndürür, aksi takdirde hata durumunda -1 döndürür.
int recvfrom (int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen)- Recvfrom işlevi BAĞLANTISIZ datagram soketlerinden veri almak için kullanılır. Bu çağrı, arabelleğe okunan bayt sayısını döndürür, aksi takdirde hata durumunda -1 döndürür.
int close (int sockfd)- Kapatma işlevi, istemci ile sunucu arasındaki iletişimi kapatmak için kullanılır. Bu çağrı, başarı durumunda 0 döndürür, aksi takdirde -1 döndürür.
int shutdown (int sockfd, int how)- Kapatma işlevi, istemci ile sunucu arasındaki bir iletişimi incelikle kapatmak için kullanılır. Bu işlev, kapatma işlevine kıyasla daha fazla kontrol sağlar. Başarı halinde 0, aksi takdirde -1 döndürür.
int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout) - Bu işlev, birden çok soketi okumak veya yazmak için kullanılır.
Soket Yardımcısı İşlevleri
int write (int fildes, const void *buf, int nbyte)- Yazma işlevi, buf ile gösterilen arabellekten nbayt baytlarını açık dosya tanımlayıcısı fildes ile ilişkili dosyaya yazmaya çalışır. Başarılı bir şekilde tamamlandıktan sonra write (), fildes ile ilişkilendirilmiş dosyaya fiilen yazılan bayt sayısını döndürür. Bu sayı hiçbir zaman nbayttan büyük değildir. Aksi takdirde -1 döndürülür.
int read (int fildes, const void *buf, int nbyte)- Okuma işlevi, açık dosya tanımlayıcısı fildes ile ilişkili dosyadan nbyte baytlarını tampon ile gösterilen arabelleğe okumaya çalışır. Başarılı bir şekilde tamamlandıktan sonra write (), fildes ile ilişkilendirilmiş dosyaya fiilen yazılan bayt sayısını döndürür. Bu sayı hiçbir zaman nbayttan büyük değildir. Aksi takdirde -1 döndürülür.
int fork (void)- Çatal işlevi yeni bir süreç yaratır. Alt süreç adı verilen yeni süreç, çağıran sürecin (ana süreç) tam bir kopyası olacaktır.
void bzero (void *s, int nbyte)- bzero işlevi, s dizesine nbyte boş bayt yerleştirir. Bu işlev, tüm soket yapılarını boş değerlerle ayarlamak için kullanılacaktır.
int bcmp (const void *s1, const void *s2, int nbyte)- bcmp işlevi, s1 bayt dizesini s2 bayt dizesiyle karşılaştırır. Her iki dizenin de nbyte bayt uzunluğunda olduğu varsayılır.
void bcopy (const void *s1, void *s2, int nbyte)- bcopy işlevi nbyte baytlarını s1 dizesinden s2 dizesine kopyalar. Çakışan dizeler doğru şekilde işlenir.
void *memset(void *s, int c, int nbyte) - memset işlevi, bzero ile aynı şekilde yapı değişkenlerini ayarlamak için de kullanılır.