書籍『Linux API。 総合ガイド»


書籍『Linux API。 総合ガイド»

こんにちは『Linux API.』という本を紹介します。 総合ガイド』(書籍の翻訳) Linux プログラミング インターフェイス)。 出版社のウェブサイトから注文でき、プロモーションコードを適用すると、 LinuxAPI 30%の割引が受けられます。

書評用の本からの抜粋:

ソケット: サーバー アーキテクチャ

この章では、反復サーバーと並列サーバーの設計の基本と、サーバー側のインターネット アプリケーションの作成を容易にする特別な inetd デーモンについて説明します。

反復サーバーと並列サーバー

一般的なソケットベースのネットワーク サーバー アーキテクチャには次の XNUMX つがあります。

  • 反復: サーバーは一度に XNUMX つのクライアントにサービスを提供し、まず XNUMX つのクライアントのリクエスト (または複数のリクエスト) を処理してから、次のクライアントに進みます。

  • 並列: サーバーは同時に複数のクライアントにサービスを提供するように設計されています。

セクション 44.8 では、FIFO キューに基づく反復サーバーの例をすでに示しています。

各クライアントは、その前にある他のクライアントが処理されるまで待機する必要があるため、通常、反復サーバーはクライアント要求をかなり迅速に処理できる状況にのみ適しています。 このアプローチの一般的な使用例は、クライアントとサーバー間で単一のリクエストと応答を交換することです。

並列サーバーは、各リクエストの処理にかなりの時間がかかる場合、またはクライアントとサーバーが長時間メッセージを交換する場合に適しています。 この章では主に、並列サーバーを設計する従来の (そして最も簡単な) 方法、つまり新しいクライアントごとに個別の子プロセスを作成する方法に焦点を当てます。 このようなプロセスは、クライアントにサービスを提供するすべての作業を実行した後、終了します。 これらのプロセスはそれぞれ独立して動作するため、同時に複数のクライアントにサービスを提供することができます。 メイン サーバー プロセス (親) の主なタスクは、新しいクライアントごとに個別の子を作成することです (プロセスの代わりに実行スレッドを作成することもできます)。

次のセクションでは、インターネット ドメイン ソケットに基づく反復サーバーと並列サーバーの例を見ていきます。 これら 862 つのサーバーは、クライアントから送信されたメッセージのコピーを返すエコー サービス (RFC XNUMX) の簡易バージョンを実装しています。

エコー反復UDPサーバー

このセクションと次のセクションでは、echo サービス用のサーバーを紹介します。 これはポート番号 7 で使用でき、UDP と TCP の両方で動作します (このポートは予約されているため、エコー サーバーは管理者権限で実行する必要があります)。

エコー UDP サーバーは常にデータグラムを読み取り、そのコピーを送信者に返します。 サーバーは一度に 56.1 つのメッセージのみを処理する必要があるため、ここでは反復アーキテクチャで十分です。 サーバーのヘッダー ファイルをリスト XNUMX-XNUMX に示します。

リスト56.1。 プログラム id_echo_sv.c および id_echo_cl.c のヘッダー ファイル

#include "inet_sockets.h" /* ソケット関数を宣言します */
#include "tlpi_hdr.h"

#define SERVICE "echo" /* UDP サービス名 */

#define BUF_SIZE 500 /* データグラムの最大サイズ
クライアントとサーバーで読み取ることができます */
________________________________________________________________________ ソケット/id_echo.h

コード リスト 56.2-XNUMX はサーバーの実装を示しています。 次の点に注意してください。

  • サーバーをデーモン モードにするには、セクション 37.2 の becomeDaemon() 関数を使用します。

  • プログラムをよりコンパクトにするために、セクション 55.12 で開発されたインターネット ドメイン ソケット ライブラリを使用します。

  • サーバーがクライアントに応答を返せない場合、syslog() 呼び出しを使用してメッセージをログに書き込みます。

実際のアプリケーションでは、syslog() を使用してメッセージをログに記録する頻度に一定の制限を課すことになるでしょう。 これにより、攻撃者がシステム ログをオーバーフローさせる可能性が排除されます。 また、各 syslog() 呼び出しはデフォルトで fsync() を使用するため、非常に高価であることに注意してください。

リスト56.2。 エコー UDP サービスを実装する反復サーバー

_________________________________________________________________sockets/id_echo_sv.c
#含む
#include "id_echo.h"
#include "become_daemon.h"

int型
main(int argc, char *argv[])
{
int SFD;
ssize_t numRead;
ソックレントレン;
構造体 sockaddr_storage claddr;
charbuf[BUF_SIZE];
char addrStr[IS_ADDR_STR_LEN];

if (becomeDaemon(0) == -1)
errExit("becomeDaemon");

sfd = inetBind(SERVICE, SOCK_DGRAM, NULL);
if (sfd == -1) {
syslog(LOG_ERR, "サーバーソケット (%s) を作成できませんでした",
strerror(errno));
終了(EXIT_FAILURE);

/* データグラムを受信し、コピーを送信者に返します */
}
のために(;;) {
len = sizeof(struct sockaddr_storage);
numRead = recvfrom(sfd, buf, BUF_SIZE, 0, (struct sockaddr *) &claddr, &len);

if (numRead == -1)
errExit("recvfrom");
if (sendto(sfd, buf, numRead, 0, (struct sockaddr *) &claddr, len)
!=numRead)
syslog(LOG_WARNING, "%s (%s) への応答のエコーエラー",
inetAddressStr((struct sockaddr *) &claddr, len,
addrStr、IS_ADDR_STR_LEN)、
strerror(errno));
}
}
_________________________________________________________________sockets/id_echo_sv.c

リスト 56.3 のプログラムを使用してサーバーをテストします。 また、セクション 55.12 で開発されたインターネット ドメイン ソケット ライブラリも使用します。 クライアント プログラムは、サーバーが配置されているネットワーク ホストの名前をコマンド ラインの最初の引数として受け取ります。 クライアントはループに入り、残りの各引数を個別のデータグラムとしてサーバーに送信し、応答としてサーバーから受信したデータグラムを読み取って出力します。

リスト56.3。 エコー UDP サービスのクライアント

#include "id_echo.h"

int型
main(int argc, char *argv[])
{
int sfd,j;
サイズ_tlen;
ssize_t numRead;
charbuf[BUF_SIZE];

if (argc < 2 || strcmp(argv[1], "--help") == 0)
useErr("%s ホスト メッセージ…n", argv[0]);

/* 最初のコマンドライン引数に基づいてサーバーアドレスを形成します */
sfd = inetConnect(argv[1], サービス, SOCK_DGRAM);
if (sfd == -1)
致命的("サーバーソケットに接続できませんでした");

/* 残りの引数を別のデータグラムとしてサーバーに送信します */
for (j = 2; j < argc; j++) {
len = strlen(argv[j]);
if (write(sfd, argv[j], len) != len)
致命的("部分的な/失敗した書き込み");

numRead = read(sfd, buf, BUF_SIZE);
if (numRead == -1)
errExit("読み取り");
printf("[%ld バイト] %.*sn", (long) numRead, (int) numRead, buf);
}
終了(EXIT_SUCCESS);
}
_________________________________________________________________sockets/id_echo_cl.c

以下は、サーバー インスタンスと XNUMX つのクライアント インスタンスを起動したときに表示される内容の例です。

$ su // 予約されたポートにバインドするには特権が必要です
パスワード:
# ./id_echo_sv // サーバーはバックグラウンドに移行します
# exit // 管理者権限を放棄します
$ ./id_echo_cl localhost hello world // このクライアントは XNUMX つのデータグラムを送信します
[5バイト] hello // クライアントはサーバーから受信した応答を出力します
[5バイト]ワールド
$ ./id_echo_cl localhost Goodbye // このクライアントは XNUMX つのデータグラムを送信します
[7バイト]さようなら

楽しくお読みいただければ幸いです)

出所: linux.org.ru