Tempah “Linux API. Panduan Komprehensif"


Tempah “Linux API. Panduan Komprehensif"

Selamat petang Saya mempersembahkan kepada perhatian anda buku “Linux API. Panduan komprehensif" (terjemahan buku Antara Muka Pengaturcaraan Linux). Ia boleh dipesan di tapak web penerbit dan jika anda menggunakan kod promosi LinuxAPI , anda akan menerima diskaun 30%.

Petikan dari buku untuk rujukan:

Soket: Seni Bina Pelayan

Dalam bab ini, kita akan membincangkan asas-asas mereka bentuk pelayan lelaran dan selari, dan juga melihat daemon khas yang dipanggil inetd, yang memudahkan untuk mencipta aplikasi pelayan Internet.

Pelayan berulang dan selari

Terdapat dua seni bina pelayan rangkaian berasaskan soket biasa:

  • berulang: pelayan melayani pelanggan satu demi satu, pertama memproses permintaan (atau beberapa permintaan) daripada satu pelanggan dan kemudian beralih ke seterusnya;

  • selari: pelayan direka untuk melayani berbilang pelanggan secara serentak.

Contoh pelayan lelaran berdasarkan baris gilir FIFO telah pun dibentangkan dalam Bahagian 44.8.

Pelayan berulang biasanya hanya sesuai dalam situasi di mana permintaan pelanggan boleh diproses dengan agak cepat, kerana setiap pelanggan terpaksa menunggu sehingga mana-mana pelanggan lain di hadapannya telah disampaikan. Kes penggunaan biasa untuk pendekatan ini ialah pertukaran permintaan dan tindak balas tunggal antara pelanggan dan pelayan.

Pelayan selari sesuai dalam kes di mana setiap permintaan mengambil masa yang banyak untuk diproses, atau di mana pelanggan dan pelayan terlibat dalam pertukaran mesej yang panjang. Dalam bab ini, kami akan memberi tumpuan terutamanya pada cara tradisional (dan paling mudah) untuk mereka bentuk pelayan selari, iaitu mencipta proses anak yang berasingan untuk setiap pelanggan baharu. Proses ini melaksanakan semua kerja untuk melayani pelanggan dan kemudian tamat. Oleh kerana setiap proses ini beroperasi secara bebas, adalah mungkin untuk melayani berbilang pelanggan secara serentak. Tugas utama proses pelayan utama (ibu bapa) adalah untuk mencipta anak yang berasingan untuk setiap pelanggan baharu (sebagai alternatif, urutan pelaksanaan boleh dibuat dan bukannya proses).

Dalam bahagian berikut, kita akan melihat contoh pelayan soket domain internet lelaran dan selari. Kedua-dua pelayan ini melaksanakan versi ringkas perkhidmatan gema (RFC 862), yang mengembalikan salinan sebarang mesej yang dihantar kepadanya oleh pelanggan.

Gema pelayan UDP berulang

Dalam bahagian ini dan seterusnya kami akan memperkenalkan pelayan untuk perkhidmatan gema. Ia tersedia pada port nombor 7 dan berfungsi pada kedua-dua UDP dan TCP (port ini dikhaskan, dan oleh itu pelayan gema mesti dijalankan dengan keistimewaan pentadbir).

Pelayan UDP gema membaca datagram secara berterusan dan mengembalikan salinannya kepada pengirim. Memandangkan pelayan hanya perlu memproses satu mesej pada satu masa, seni bina berulang akan mencukupi. Fail pengepala untuk pelayan ditunjukkan dalam Penyenaraian 56.1.

Penyenaraian 56.1. Fail pengepala untuk program id_echo_sv.c dan id_echo_cl.c

#include "inet_sockets.h" /* Mengisytiharkan fungsi soket kami */
#include "tlpi_hdr.h"

#define SERVICE "echo" /* nama perkhidmatan UDP */

#define BUF_SIZE 500 /* Saiz maksimum datagram yang
boleh dibaca oleh klien dan pelayan */
_____________________________________________________________________soket/id_echo.h

Penyenaraian 56.2 menunjukkan pelaksanaan pelayan. Perkara-perkara berikut patut diberi perhatian:

  • untuk meletakkan pelayan ke dalam mod daemon, kami menggunakan fungsi becomeDaemon() daripada bahagian 37.2;

  • untuk menjadikan program lebih padat, kami menggunakan perpustakaan untuk bekerja dengan soket domain Internet, dibangunkan dalam bahagian 55.12;

  • jika pelayan tidak dapat mengembalikan respons kepada klien, ia menulis mesej kepada log menggunakan panggilan syslog().

Dalam aplikasi sebenar, kami mungkin akan mengenakan beberapa had pada kekerapan mesej log menggunakan syslog(). Ini akan menghapuskan kemungkinan penyerang melimpahi log sistem. Di samping itu, jangan lupa bahawa setiap panggilan ke syslog() agak mahal, kerana ia menggunakan fsync() secara lalai.

Penyenaraian 56.2. Pelayan lelaran yang melaksanakan perkhidmatan gema UDP

_________________________________________________________________soket/id_echo_sv.c
#termasuk
#include "id_echo.h"
#include "become_daemon.h"

int
utama(int argc, char *argv[])
{
int sfd;
ssize_t numRead;
socklen_t len;
struct sockaddr_storage claddr;
char buf[BUF_SIZE];
char addrStr[IS_ADDR_STR_LEN];

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

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

/* Terima datagram dan kembalikan salinannya kepada penghantar */
}
untuk (;;) {
len = sizeof(struct sockaddr_storage);
numRead = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);

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

Untuk menguji operasi pelayan, kami menggunakan program daripada Penyenaraian 56.3. Ia juga menggunakan perpustakaan untuk bekerja dengan soket domain Internet, yang dibangunkan dalam bahagian 55.12. Sebagai hujah baris arahan pertama, program klien mengambil nama nod rangkaian di mana pelayan berada. Pelanggan memasuki gelung di mana ia menghantar setiap argumen yang tinggal kepada pelayan sebagai datagram yang berasingan, dan kemudian membaca dan mencetak datagram yang diterima daripada pelayan sebagai tindak balas.

Penyenaraian 56.3. Pelanggan untuk perkhidmatan gema UDP

#include "id_echo.h"

int
utama(int argc, char *argv[])
{
int sfd, j;
saiz_t len;
ssize_t numRead;
char buf[BUF_SIZE];

if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s hos msg…n", argv[0]);

/* Bentuk alamat pelayan berdasarkan hujah baris arahan pertama */
sfd = inetConnect(argv[1], SERVICE, SOCK_DGRAM);
jika (sfd == -1)
fatal("Tidak dapat menyambung ke soket pelayan");

/* Hantar argumen yang tinggal ke pelayan dalam bentuk datagram yang berasingan */
untuk (j = 2; j < argc; j++) {
len = strlen(argv[j]);
jika (tulis(sfd, argv[j], len) != len)
fatal("tulisan separa/gagal");

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

Di bawah ialah contoh perkara yang akan kita lihat apabila menjalankan pelayan dan dua contoh klien:

$su // Keistimewaan diperlukan untuk mengikat ke port yang dikhaskan
kata laluan:
# ./id_echo_sv // Pelayan masuk ke mod latar belakang
# exit // Lepaskan hak pentadbir
$ ./id_echo_cl localhost hello world // Pelanggan ini menghantar dua datagram
[5 bait] hello // Pelanggan memaparkan respons yang diterima daripada pelayan
[5 bait] dunia
$ ./id_echo_cl localhost selamat tinggal // Pelanggan ini menghantar satu datagram
[7 bait] selamat tinggal

Saya ucapkan selamat membaca)

Sumber: linux.org.ru