Kitap "Linux API. Kapsamlı rehber »


Kitap "Linux API. Kapsamlı rehber »

Tünaydın “Linux API” kitabını dikkatinize sunuyorum. Kapsamlı rehber "(kitabın çevirisi Linux Programlama Arayüzü). Yayıncının web sitesinden sipariş edilebilir ve promosyon kodunu uygularsanız LinuxAPI %30 indirim alacaksınız.

Kitaptan incelenmek üzere bir alıntı:

Soketler: sunucu mimarisi

Bu bölümde yinelemeli ve paralel sunucular tasarlamanın temellerinin yanı sıra, sunucu tarafı İnternet uygulamalarının oluşturulmasını kolaylaştıran özel bir inetd arka plan programı tartışacağız.

Yineleme ve Paralel Sunucular

İki yaygın soket tabanlı ağ sunucusu mimarisi vardır:

  • yinelemeli: sunucu, istemcilere teker teker hizmet verir, önce bir istemciden gelen bir isteği (veya birkaç isteği) işler ve ardından diğerine geçer;

  • paralel: sunucu aynı anda birden fazla istemciye hizmet verecek şekilde tasarlanmıştır.

Bölüm 44.8'de FIFO kuyruklarına dayalı bir yineleme sunucusu örneği zaten verilmiştir.

Yineleme sunucuları genellikle yalnızca istemci isteklerinin oldukça hızlı bir şekilde işlenebildiği durumlarda uygundur, çünkü her istemci, önündeki diğer istemcilere hizmet verilene kadar beklemek zorundadır. Bu yaklaşımın yaygın bir kullanım örneği, bir istemci ile bir sunucu arasında tekli isteklerin ve yanıtların değişimidir.

Paralel sunucular, her isteğin işlenmesinin önemli miktarda zaman aldığı veya istemci ve sunucu arasında uzun bir mesaj alışverişinin olduğu durumlarda uygundur. Bu bölümde esas olarak paralel sunucular tasarlamanın geleneksel (ve en kolay) yolu olan her yeni istemci için ayrı bir alt süreç oluşturmak üzerine odaklanacağız. Böyle bir süreç, müşteriye hizmet vermenin tüm işini yapar ve sonrasında sona erer. Bu süreçlerin her biri birbirinden bağımsız çalıştığı için aynı anda birden fazla müşteriye hizmet vermek mümkündür. Ana sunucu işleminin (ana) ana görevi, her yeni istemci için ayrı bir alt öğe oluşturmaktır (alternatif olarak, işlemler yerine yürütme iş parçacıkları oluşturabilirsiniz).

İlerleyen bölümlerde internet alan soketlerini temel alan yinelemeli ve paralel sunucu örneklerine bakacağız. Bu iki sunucu, istemci tarafından kendisine gönderilen herhangi bir mesajın bir kopyasını döndüren yankı hizmetinin (RFC 862) basitleştirilmiş bir sürümünü uygular.

yankı yineleme udp sunucusu

Bu ve sonraki bölümde echo hizmeti için sunucuları tanıtacağız. 7 numaralı bağlantı noktasında bulunur ve hem UDP hem de TCP üzerinden çalışır (bu bağlantı noktası ayrılmıştır ve bu nedenle yankı sunucusunun yönetici ayrıcalıklarıyla çalıştırılması gerekir).

echo UDP sunucusu sürekli olarak datagramları okur ve bunların bir kopyasını gönderene geri gönderir. Sunucunun aynı anda yalnızca bir mesajı işlemesi gerektiğinden, yinelemeli bir mimari burada yeterli olacaktır. Sunucular için başlık dosyası Liste 56.1-XNUMX'de gösterilmektedir.

Liste 56.1. id_echo_sv.c ve id_echo_cl.c programları için başlık dosyası

#include "inet_sockets.h" /* Soket fonksiyonlarımızı bildirir */
#include "tlpi_hdr.h"

#define SERVICE "echo" /* UDP hizmet adı */

#define BUF_SIZE 500 /* Maksimum veri birimi boyutu
istemci ve sunucu tarafından okunabilir */
____________________________________________________________________ prizler/id_echo.h

Liste 56.2-XNUMX sunucu uygulamasını gösterir. Aşağıdaki noktalara dikkat etmek önemlidir:

  • sunucuyu daemon moduna geçirmek için Bölüm 37.2'deki makeDaemon() fonksiyonunu kullanıyoruz;

  • programı daha kompakt hale getirmek için bölüm 55.12'de geliştirilen internet etki alanı soket kütüphanesini kullanıyoruz;

  • sunucu istemciye bir yanıt döndüremezse syslog() çağrısını kullanarak günlüğe bir mesaj yazar.

Gerçek bir uygulamada, büyük ihtimalle syslog() kullanarak mesajların günlüğe kaydedilme sıklığına belirli bir sınır koyarız. Bu, bir saldırganın sistem günlüğünü taşması olasılığını ortadan kaldıracaktır. Ayrıca, varsayılan olarak fsync() işlevini kullandığından her syslog() çağrısının oldukça pahalı olduğunu unutmayın.

Liste 56.2. echo UDP hizmetini uygulayan bir yineleme sunucusu

_____________________________________________________________soketler/id_echo_sv.c
#katmak
#include "id_echo.h"
#include "become_daemon.h"

int
main(int argc, char *argv[])
{
int sfd;
ssize_t numRead;
socklen_tlen;
struct sockaddr_storage claddr;
charbuf[BUF_SIZE];
char addrStr[IS_ADDR_STR_LEN];

if (Daemon haline gelir(0) == -1)
errExit("Daemon ol");

sfd = inetBind(SERVICE, SOCK_DGRAM, NULL);
if (sfd == -1) {
syslog(LOG_ERR, "Sunucu soketi oluşturulamadı (%s)",
strerror(hata));
çıkış(EXIT_FAILURE);

/* Datagramları al ve kopyalarını gönderenlere geri gönder */
}
için (;;) {
len = sizeof(struct sockaddr_storage);
numRead = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);

if (numRead == -1)
errExit("alınan kaynak");
if (sendto(sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
!=sayıOku)
syslog(LOG_WARNING, "%s (%s) yanıtını yankılarken hata oluştu",
inetAddressStr((struct sockaddr *) &claddr, len,
addrStr, IS_ADDR_STR_LEN),
strerror(hata));
}
}
_____________________________________________________________soketler/id_echo_sv.c

Sunucuyu test etmek için liste 56.3'teki programı kullanıyoruz. Ayrıca Bölüm 55.12'de geliştirilen İnternet etki alanı soket kitaplığını da kullanır. İstemci programı, komut satırındaki ilk argüman olarak sunucunun bulunduğu ağ ana bilgisayarının adını alır. İstemci, kalan argümanların her birini ayrı datagramlar olarak sunucuya gönderdiği ve ardından yanıt olarak sunucudan alınan datagramları okuyup çıktısını aldığı bir döngüye girer.

Liste 56.3. echo UDP hizmeti için istemci

#include "id_echo.h"

int
main(int argc, char *argv[])
{
int sfd,j;
size_tlen;
ssize_t numRead;
charbuf[BUF_SIZE];

if (argc < 2 || strcmp(argv[1], "--help") == 0)
useErr("%s ana makine mesajı…n", argv[0]);

/* İlk komut satırı argümanına göre sunucu adresini oluşturun */
sfd = inetConnect(argv[1], SERVICE, SOCK_DGRAM);
eğer (sfd == -1)
fatal("Sunucu soketine bağlanılamadı");

/* Bağımsız değişkenlerin geri kalanını sunucuya ayrı datagramlar olarak gönder */
for (j = 2; j < argc; j++) {
len = strlen(argv[j]);
if (write(sfd, argv[j], len) != len)
fatal("kısmi/başarısız yazma");

numRead = read(sfd, buf, BUF_SIZE);
if (numRead == -1)
errExit("oku");
printf("[%ld bytes] %.*sn", (long) numRead, (int) numRead, buf);
}
çıkış(EXIT_SUCCESS);
}
_____________________________________________________________soketler/id_echo_cl.c

Sunucuyu ve iki istemci örneğini başlattığımızda göreceğimiz şeyin bir örneği aşağıdadır:

$ su // Ayrılmış bir bağlantı noktasına bağlanmak için ayrıcalıklar gerektirir
Parola:
# ./id_echo_sv // Sunucu arka plana gider
# çıkış // Yönetici haklarından vazgeç
$ ./id_echo_cl localhost merhaba dünya // Bu istemci iki datagram gönderir
[5 bayt] merhaba // İstemci, sunucudan alınan yanıtın çıktısını verir
[5 bayt] dünya
$ ./id_echo_cl localhost elveda // Bu istemci bir datagram gönderir
[7 bayt] elveda

Keyifli okumalar dilerim)

Kaynak: linux.org.ru