Pesan “Linux API. Panduan Komprehensif"


Pesan “Linux API. Panduan Komprehensif"

Selamat siang Saya mempersembahkan kepada Anda buku “Linux API. Panduan komprehensif" (terjemahan buku Antarmuka Pemrograman Linux). Itu dapat dipesan di situs web penerbit, dan jika Anda menerapkan kode promosi LinuxAPI , Anda akan menerima diskon 30%.

Kutipan dari buku untuk referensi:

Soket: Arsitektur Server

Pada bab ini, kita akan membahas dasar-dasar perancangan server iteratif dan paralel, dan juga melihat daemon khusus yang disebut inetd, yang memudahkan pembuatan aplikasi server Internet.

Server berulang dan paralel

Ada dua arsitektur server jaringan berbasis soket yang umum:

  • berulang: server melayani klien satu per satu, pertama-tama memproses permintaan (atau beberapa permintaan) dari satu klien dan kemudian melanjutkan ke klien berikutnya;

  • paralel: server dirancang untuk melayani banyak klien secara bersamaan.

Contoh server berulang berdasarkan antrian FIFO telah disajikan di Bagian 44.8.

Server berulang biasanya hanya cocok dalam situasi di mana permintaan klien dapat diproses dengan cukup cepat, karena setiap klien terpaksa menunggu hingga klien lain di depannya dilayani. Kasus penggunaan umum untuk pendekatan ini adalah pertukaran permintaan dan tanggapan tunggal antara klien dan server.

Server paralel cocok digunakan jika setiap permintaan membutuhkan banyak waktu untuk diproses, atau saat klien dan server terlibat dalam pertukaran pesan yang panjang. Dalam bab ini, kita terutama akan fokus pada cara tradisional (dan paling sederhana) dalam merancang server paralel, yaitu membuat proses anak terpisah untuk setiap klien baru. Proses ini melakukan semua pekerjaan untuk melayani klien dan kemudian berakhir. Karena masing-masing proses ini beroperasi secara independen, maka dimungkinkan untuk melayani banyak klien secara bersamaan. Tugas utama dari proses server utama (induk) adalah membuat anak terpisah untuk setiap klien baru (sebagai alternatif, utas eksekusi dapat dibuat sebagai ganti proses).

Pada bagian berikut, kita akan melihat contoh server soket domain internet iteratif dan paralel. Kedua server ini menerapkan versi sederhana dari layanan gema (RFC 862), yang mengembalikan salinan pesan apa pun yang dikirim oleh klien.

Gema server UDP berulang

Di bagian ini dan selanjutnya kami akan memperkenalkan server untuk layanan echo. Ini tersedia pada port nomor 7 dan berfungsi pada UDP dan TCP (port ini dicadangkan, dan oleh karena itu server gema harus dijalankan dengan hak administrator).

Server echo UDP terus membaca datagram dan mengembalikan salinannya ke pengirim. Karena server hanya perlu memproses satu pesan dalam satu waktu, arsitektur iteratif sudah cukup. File header untuk server ditunjukkan pada Listing 56.1.

Daftar 56.1. File header untuk program id_echo_sv.c dan id_echo_cl.c

#include "inet_sockets.h" /* Mendeklarasikan fungsi soket kita */
#sertakan "tlpi_hdr.h"

#define LAYANAN "echo" /* Nama layanan UDP */

#define BUF_SIZE 500 /* Ukuran maksimum datagram itu
dapat dibaca oleh klien dan server */
_______________________________________________________sockets/id_echo.h

Listing 56.2 menunjukkan implementasi server. Poin-poin berikut perlu diperhatikan:

  • untuk menempatkan server ke mode daemon, kita menggunakan fungsi menjadiDaemon() dari bagian 37.2;

  • untuk membuat program lebih ringkas, kami menggunakan perpustakaan untuk bekerja dengan soket domain Internet, yang dikembangkan di bagian 55.12;

  • jika server tidak dapat mengembalikan respons ke klien, server akan menulis pesan ke log menggunakan panggilan syslog().

Dalam aplikasi nyata, kami mungkin akan menerapkan batasan tertentu pada frekuensi pencatatan pesan menggunakan syslog(). Ini akan menghilangkan kemungkinan penyerang membanjiri log sistem. Selain itu, jangan lupa bahwa setiap panggilan ke syslog() cukup mahal, karena menggunakan fsync() secara default.

Daftar 56.2. Server iterasi yang mengimplementasikan layanan gema UDP

_________________________________________________________________sockets/id_echo_sv.c
#termasuk
#sertakan "id_echo.h"
#sertakan "menjadi_daemon.h"

int
utama(ke dalam argc, karakter *argv[])
{
ke dalam sfd;
ssize_t angkaBaca;
socklen_t len;
struct sockaddr_storage claddr;
karakter buf[BUF_SIZE];
karakter addrStr[IS_ADDR_STR_LEN];

jika (menjadiDaemon(0) == -1)
errExit("menjadiDaemon");

sfd = inetBind(LAYANAN, SOCK_DGRAM, NULL);
jika (sfd == -1) {
syslog(LOG_ERR, "Tidak dapat membuat soket server (%s)",
strerror(errno));
keluar(EXIT_FAILURE);

/* Menerima datagram dan mengembalikan salinannya ke pengirim */
}
untuk (;;) {
len = sizeof(struct sockaddr_storage);
numRead = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);

jika (angkaBaca == -1)
errExit("recvfrom");
if (kirim ke(sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
!= angkaBaca)
syslog(LOG_WARNING, "Kesalahan menggemakan respons ke %s (%s)",
inetAddressStr((struct sockaddr *) &claddr, len,
addrStr, IS_ADDR_STR_LEN),
strerror(errno));
}
}
_________________________________________________________________sockets/id_echo_sv.c

Untuk menguji pengoperasian server, kami menggunakan program dari Listing 56.3. Ia juga menggunakan perpustakaan untuk bekerja dengan soket domain Internet, yang dikembangkan di bagian 55.12. Sebagai argumen baris perintah pertama, program klien mengambil nama node jaringan tempat server berada. Klien memasuki loop di mana ia mengirimkan setiap argumen yang tersisa ke server sebagai datagram terpisah, dan kemudian membaca dan mencetak datagram yang diterimanya dari server sebagai respons.

Daftar 56.3. Klien untuk layanan gema UDP

#sertakan "id_echo.h"

int
utama(ke dalam argc, karakter *argv[])
{
ke dalam sfd,j;
ukuran_t len;
ssize_t angkaBaca;
karakter buf[BUF_SIZE];

jika (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s pesan host…n", argv[0]);

/* Bentuk alamat server berdasarkan argumen baris perintah pertama */
sfd = inetConnect(argv[1], LAYANAN, SOCK_DGRAM);
jika (sfd == -1)
fatal("Tidak dapat terhubung ke soket server");

/* Mengirim argumen yang tersisa ke server dalam bentuk datagram terpisah */
untuk (j = 2; j < argc; j++) {
len = strlen(argv[j]);
jika (tulis(sfd, argv[j], len) != len)
fatal("penulisan sebagian/gagal");

angkaBaca = baca(sfd, buf, BUF_SIZE);
jika (angkaBaca == -1)
errKeluar("baca");
printf("[%ld bytes] %.*sn", (panjang) numRead, (int) numRead, buf);
}
keluar(EXIT_SUCCESS);
}
_________________________________________________________________sockets/id_echo_cl.c

Di bawah ini adalah contoh dari apa yang akan kita lihat ketika menjalankan server dan dua instance klien:

$su // Hak istimewa diperlukan untuk mengikat ke port yang dicadangkan
Kata sandi:
# ./id_echo_sv // Server masuk ke mode latar belakang
# exit // Menyerahkan hak administrator
$ ./id_echo_cl localhost hello world // Klien ini mengirimkan dua datagram
[5 bytes] hello // Klien menampilkan respon yang diterima dari server
[5 byte] dunia
$ ./id_echo_cl localhost selamat tinggal // Klien ini mengirimkan satu datagram
[7 byte] selamat tinggal

Saya harap Anda mendapatkan bacaan yang menyenangkan)

Sumber: linux.org.ru