名前つきパイプ(2)

名前なしパイプ(2)と同じようなことをここではします. また整数の加算です.

クライアントサイドプログラム

/* client.c */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>

#define FIFO0 "./FIFO0" //Read
#define FIFO1 "./FIFO1" //Write

void error_message(const char *name);
void unlink_pipe(void);

int main(int argc, char **argv)
{
    int fd0, fd1;
    char buff[32], result[32];

    if((fd0 = open(FIFO0, O_RDONLY)) == EOF || (fd1 = open(FIFO1, O_WRONLY)) == EOF)
        error_message("open");

    printf("NumA:");
    fgets(buff, 32, stdin);
    if(write(fd1, buff, strlen(buff) + 1) == EOF)
        error_message("write");

    printf("NumB:");
    fgets(buff, 32, stdin);
    if(write(fd1, buff, strlen(buff) + 1) == EOF)
        error_message("write");

    if(read(fd0, result, 32) == EOF)
        error_message("read");

    printf("Answer = %s\n", result);

    unlink_pipe();

    return 0;
}

void error_message(const char *name) {
    perror(name);
    exit(EXIT_FAILURE);
}

void unlink_pipe(void) {
    if(unlink(FIFO0) == EOF)
        error_message("unlink");
    if(unlink(FIFO1) == EOF)
        error_message("unlink");
}
サーバーサイドプログラム
/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

#define FIFO0 "./FIFO0" //Write
#define FIFO1 "./FIFO1" //Read

void error_message(const char *name);

int main(int argc, char **argv)
{
    int fd0, fd1;
    int na, nb, nc;
    char buff[32], result[32];

    if(access(FIFO0, 0777) == EOF)
        mkfifo(FIFO0, 0777);
    if(access(FIFO1, 0777) == EOF)
        mkfifo(FIFO1, 0777);

    if((fd0 = open(FIFO0, O_WRONLY)) == EOF)
        error_message("open");
    if((fd1 = open(FIFO1, O_RDONLY)) == EOF)
        error_message("open");

    if(read(fd1, buff, 32) == EOF)
        error_message("read");
    na = atoi(buff);

    printf("Get Number A = %d\n", na);

    if(read(fd1, buff, 32) == EOF)
        error_message("read");
    nb = atoi(buff);

    printf("Get Number B = %d\n", nb);

    nc = na + nb;

    printf("Returned Answer to Client...\n");

    sprintf(result, "%d", nc);

    if(write(fd0, result, strlen(result) + 1) == EOF)
        error_message("write");

    return 0;
}

void error_message(const char *name) {
    perror(name);
    exit(EXIT_FAILURE);
}
実行例

$ ./server
Get Number A : 1234
Get Number B : 4567
Returned Answer to Client...

$ ./client
NumA:1234
NumB:4567
Answer = 5801


プログラムの説明

クライアントサイドの説明

#define FIFO0 "./FIFO0" //Read
#define FIFO1 "./FIFO1" //Write
                            
if((fd0 = open(FIFO0, O_RDONLY)) == EOF || (fd1 = open(FIFO1, O_WRONLY)) == EOF)
    error_message("open");
                            
"define"で指定した名前つきパイプを開きます.
printf("NumA:");
fgets(buff, 32, stdin);
if(write(fd1, buff, strlen(buff) + 1) == EOF)
    error_message("write");

printf("NumB:");
fgets(buff, 32, stdin);
if(write(fd1, buff, strlen(buff) + 1) == EOF)
    error_message("write");
整数を文字列として名前つきパイプに書き込みます.
この時, 同じファイルディスクリプタに書き込んでいますが, 実際はサーバーを実行しているため違う値としてサーバー側に書き込まれています.
if(read(fd0, result, 32) == EOF)
    error_message("read");

printf("Answer = %s\n", result);
サーバーから送信されたデータを読み込み, 表示させます.

サーバサイドの説明
if(access(FIFO0, 0777) == EOF)
    mkfifo(FIFO0, 0777);
if(access(FIFO1, 0777) == EOF)
    mkfifo(FIFO1, 0777);
"access"関数でファイルが存在しない場合のみ, 名前つきパイプを作成させる.
if(read(fd1, buff, 32) == EOF)
    error_message("read");
na = atoi(buff);

if(read(fd1, buff, 32) == EOF)
    error_message("read");
nb = atoi(buff);
名前つきパイプを通じて取得したデータを整数に変換してあらかじめ用意した変数に格納.
sprintf(result, "%d", nc);

if(write(fd0, result, strlen(result) + 1) == EOF)
    error_message("write");
加算処理させた変数"nc"を文字列"result"に格納し書き込み専用で開いた名前つきパイプに書き込む.

プログラム別に記述しましたが, 一連の流れはプログラム同士が連帯しているので実行しながら確認してください.