[Linux オペレーティング システム] メッセージ キューに基づく銀行管理システム <クライアント> コードの詳細な分析

情報キューをベースにした銀行管理システムクライアントのプロジェクトコードを詳しく解説しています。主にクライアント上での口座開設、入出金などの操作を紹介しています。コードは比較的シンプルですが、各コードはソースコード 主に
Linux システムプログラミングフェーズプロジェクト: メッセージキューをベースにした銀行管理システム
この記事はそのコードをもとに詳しく解説したものであり、彼のブログを読んで私が詳しく調べた記録でもあります。
ここに画像の説明を挿入します


記事ディレクトリ


ヘッダー ファイルと構造

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int g_reqid; //作为请求的消息队列的返回id
int g_resid;  //作为应答消息队列的返回id
typedef struct msgbuf{
    
    
    long mtype;         //消息类型
    char id[100];       //账户
    char name[256];     //用户名
    char pw[9];        //密码
    float money;       //银行卡余额
}userm;
typedef struct tag_OpenRespond{
    
    
  long   type;
  char   id[100];      //账户
  char   msg[256];
  float  money;       //银行卡余额
}RES;                 //让客户端从应答消息队列读到的反馈存到这里

メイン機能

int main()
{
    
    
    while(1)
    {
    
    
        menu();
        int a;
        printf("请输入要执行的操作!\n");
        scanf("%d",&a);
        switch(a)
        {
    
    
            case 1:Account();break;//开户
            case 2:Deposit();break;//存款
            case 3:withdrawal();break;//取款
            case 4:Inquire();break;//查询
            case 5:Transfer();break;//转账
            case 6:Logout();break;//注销
            case 7:
                return 0;

        }
    }
}

main 関数は非常に単純です。

  • 主にループ本体ですwhile(1)
  • 次に、ディレクトリを出力しますmenu()
  • ユーザーは数値を入力して操作する機能を選択しますが、これは以下のswitch選択文に相当します。
  • ユーザーが 1 を入力すると、口座開設を意味し、対応する機能はAccount();です。
  • ユーザーが 2 を入力した場合、それは預金であり、対応する機能は ですDeposit()
  • ユーザーが 3 を入力すると、引き出しを意味し、対応する機能はWithdrawal();です。
  • ユーザーが 4 を入力した場合、それはクエリであり、対応する関数はInquire();です。
  • ユーザーが 5 を入力すると転送となり、対応する機能はTransfer();となります。
  • ユーザーが 6 を入力すると、ログアウトすることを意味し、対応する機能はLogout();です。
  • ユーザーが「7」を入力すると終了します。

次のステップでは、これらの関数の問題を段階的に解決します。


メニュー

void menu()
{
    
    
    printf("*********欢迎来到小黑银行!************\n");
    printf("**************1.开户******************\n");
    printf("**************2.存款******************\n");
    printf("**************3.取款******************\n");
    printf("**************4.查询******************\n");
    printf("**************5.转账******************\n");
    printf("**************6.销户******************\n");
    printf("**************7.退出******************\n");
}

メニュー機能の実装は非常に簡単です 標準出力のみが必要です ポートの問題を考慮する必要はありません ポートは以下の関数で実装されます


1. 口座を開設する

void Account()
{
    
    
    key_t kid1,kid2;

    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;//错误提示
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1) 
    {
    
       
        perror("msgget");
        return;
    }   
    
    userm a;
    printf("请输入要注册的身份号!\n");
    scanf("%s",a.id);

    printf("请输入要注册的用户名!\n");
    scanf("%s",a.name);

    printf("请输入要注册的密码!\n");
    scanf("%s",a.pw);

    printf("请输入要注册的余额!\n");
    scanf("%f",&a.money);
    //往请求消息队列写
    a.mtype = 1;   //消息类型为1,开户用
    msgsnd(g_reqid,&a,sizeof(userm)-sizeof(long),0);

    //读应答消息队列
    RES buf;
    msgrcv(g_resid,&buf,sizeof(buf),1,0);  //1类消息,开户用
    printf("%s\n",buf.msg);

    return;

}

コードの説明

このコードは、2 つのメッセージ キューを開き、そこからメッセージを読み書きする C 言語関数です。

まず、ftok関数を使用して、メッセージ キューを一意に識別する 2 つのキー値を生成します。ftokこの関数にはファイル パスと整数値が必要で、これらのパラメーターに基づいて一意のキー値を生成します。

次に、msgget関数を使用して要求メッセージ キューと応答メッセージ キューをオープンします。msggetこの関数は 2 つのパラメーターを受け入れます。1 つはキー値、もう 1 つはフラグです。IPC_CREATメッセージ キューが存在しない場合は新しいメッセージ キューを作成し、0644アクセス許可が読み取りと書き込みに設定されていることを示します。

次に、ユーザーの登録情報を格納するuserm構造体変数を定義します。a次に、ユーザーは と の関数を使用して ID 番号、ユーザー名、パスワード、残高をそれぞれ入力するように求められprintfscanfユーザーが入力した値は構造体変数の対応するフィールドに保存されますa

aその後、フィールドは1 に設定されmtype、このメッセージが口座開設用であることを示します。次に、msgsnd関数を使用して構造体変数をaリクエスト メッセージ キューに書き込みます。msgsndこの関数は、メッセージ キューの ID、メッセージへのポインター、メッセージのサイズ、メッセージのタイプ、およびフラグ ビットの 5 つのパラメーターを受け入れます。ここでのメッセージ タイプは 1 で、アカウントの開設に使用されることを意味します。

最後に、msgrcv関数を使用して応答メッセージ キューからメッセージを読み取ります。msgrcvこの関数は、メッセージ キューの ID、メッセージへのポインター、メッセージのサイズ、メッセージのタイプ、およびフラグ ビットの 5 つのパラメーターを受け入れます。ここでのメッセージ タイプは 1 で、アカウントの開設に使用されることを意味します。読み取られたメッセージは、bufという名前の構造体変数に格納されます。次に、printf関数を使用してメッセージの内容を出力します。

この関数全体の目的は、ユーザーの登録情報をリクエスト メッセージ キューに書き込み、口座開設結果をレスポンス メッセージ キューから読み出して出力することです。


2. 入金

void Deposit()//存款业务
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    userm c;
    printf("请输入要存款用户的身份号!\n");
    scanf("%s",c.id);
   
    printf("请输入要存款用户的用户名!\n");
    scanf("%s",c.name);
    
    printf("请输入要存款用户的密码!\n");
    scanf("%s",c.pw);
   
    printf("请输入要存款的金额!\n");
    scanf("%f",&c.money);
    //往请求消息队列写
    c.mtype = 2;   //消息类型为2,存款用
    msgsnd(g_reqid,&c,sizeof(userm)-sizeof(long),0);
    
    //读应答消息队列
    RES buf2;
    msgrcv(g_resid,&buf2,sizeof(buf2),2,0);  //2类消息,存款用
    printf("%s\n",buf2.msg);
    
    return;
}

1. メッセージキューのキー値を作成します。

key_t kid1,kid2;
kid1 = ftok("/home/whs/002/0706",1); //键值
kid2 = ftok("/home/whs/002/0706",2);
  • ftokこの関数は、メッセージ キューを作成するための識別子として一意のキー値を生成するために使用されます。
  • 最初のパラメータは、キー値の生成に使用されるパス名です。
  • 2 番目のパラメーターは、キー値の生成に使用される整数です。
  • ここでは、2 つの異なるパスと整数をパラメーターとして使用して、2 つの異なるキー値を生成します。

2. リクエストメッセージキューをオープンする

g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
if(g_reqid== -1)
{
    
    
    perror("msgget");
    return;
}
  • msgget関数は、メッセージ キューを開くか作成するために使用されます。
  • 最初のパラメータはメッセージ キューのキー値です。
  • 2 番目のパラメーターはフラグで、IPC_CREATメッセージ キューが存在しない場合は作成すること、0644つまりアクセス許可を設定することを意味します。
  • この関数はメッセージ キューの識別子を返します。戻り値が -1 の場合は、オープンまたは作成が失敗したことを意味します。

3. 応答メッセージキューを開く

g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
if(g_resid == -1)
{
    
    
    perror("msgget");
    return;
}
  • また、msggetこの関数を使用してメッセージ キューを開くか作成します。今回は 2 番目のキー値を使用します。
  • 開くか作成に失敗すると、エラー メッセージが出力されて返されます。

4.入金情報を入力する

userm c;
printf("请输入要存款用户的身份号!\n");
scanf("%s",c.id);

printf("请输入要存款用户的用户名!\n");
scanf("%s",c.name);

printf("请输入要存款用户的密码!\n");
scanf("%s",c.pw);

printf("请输入要存款的金额!\n");
scanf("%f",&c.money);
  • ユーザー関連情報を保存するために という名前の構造体を作成しますcuserm
  • ユーザーの識別番号、ユーザー名、パスワード、入金額を順に入力します。

5. リクエストをメッセージキューに書き込みます

c.mtype = 2;   //消息类型为2,存款用
msgsnd(g_reqid,&c,sizeof(userm)-sizeof(long),0);
  • メッセージ タイプを 2 に設定し、これが入金リクエストであることを示します。
  • msgsndこの関数を使用して、c構造体をリクエスト メッセージ キューに書き込みます。
  • sizeof(userm)-sizeof(long)送信されるメッセージのサイズから、longtype のメッセージ タイプ フィールドのサイズを引いたものを表します。

6. 応答メッセージキューを読み取ります。

RES buf2;
msgrcv(g_resid,&buf2,sizeof(buf2),2,0);  //2类消息,存款用
printf("%s\n",buf2.msg);
  • 応答メッセージを受信するための という名前の構造体を作成しますbuf2RES
  • この関数を使用してmsgrcv、応答メッセージ キューからメッセージを読み取ります。
  • 最初のパラメータはメッセージ キューの識別子です。
  • 2 番目のパラメータは、メッセージを受信するバッファです。
  • 3 番目のパラメータは、受信したメッセージのサイズです。
  • 4 番目のパラメーターはメッセージ タイプで、ここでは 2 で、デポジットを受け取るための応答メッセージを示します。
  • 最後のパラメータはフラグで、0 はデフォルトの動作を示します。
  • 受信した応答メッセージを印刷します。

7. 戻る

return;
  • デポジットビジネス関数の実行を終了し、呼び出された場所に戻ります。

3. 退会

void withdrawal()//取款业务
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    userm d;
    printf("请输入要取款用户的身份号!\n");
    scanf("%s",d.id);
   
    printf("请输入要取款用户的用户名!\n");
    scanf("%s",d.name);
    
    printf("请输入要取款用户的密码!\n");
    scanf("%s",d.pw);
   
    printf("请输入要取款的金额!\n");
    scanf("%f",&d.money);
    //往请求消息队列写
    d.mtype = 3;   //消息类型为3,取款用
    msgsnd(g_reqid,&d,sizeof(userm)-sizeof(long),0);
    
    //读应答消息队列
    RES buf3;
    msgrcv(g_resid,&buf3,sizeof(buf3),3,0);  //3类消息,取款用
    printf("%s\n",buf3.msg);
    
    return;
}

1. メッセージキューのキー値を作成します。

key_t kid1,kid2;
kid1 = ftok("/home/whs/002/0706",1); //键值
kid2 = ftok("/home/whs/002/0706",2);
  • ftokこの関数は、メッセージ キューを作成するための識別子として一意のキー値を生成するために使用されます。
  • 最初のパラメータは、キー値の生成に使用されるパス名です。
  • 2 番目のパラメーターは、キー値の生成に使用される整数です。
  • ここでは、2 つの異なるパスと整数をパラメーターとして使用して、2 つの異なるキー値を生成します。

2. リクエストメッセージキューをオープンする

g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
if(g_reqid== -1)
{
    
    
    perror("msgget");
    return;
}
  • msgget関数は、メッセージ キューを開くか作成するために使用されます。
  • 最初のパラメータはメッセージ キューのキー値です。
  • 2 番目のパラメーターはフラグで、IPC_CREATメッセージ キューが存在しない場合は作成すること、0644つまりアクセス許可を設定することを意味します。
  • この関数はメッセージ キューの識別子を返します。戻り値が -1 の場合は、オープンまたは作成が失敗したことを意味します。

3. 応答メッセージキューを開く

g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
if(g_resid == -1)
{
    
    
    perror("msgget");
    return;
}
  • また、msggetこの関数を使用してメッセージ キューを開くか作成します。今回は 2 番目のキー値を使用します。
  • 開くか作成に失敗すると、エラー メッセージが出力されて返されます。

4.出金情報を入力します

userm d;
printf("请输入要取款用户的身份号!\n");
scanf("%s",d.id);

printf("请输入要取款用户的用户名!\n");
scanf("%s",d.name);

printf("请输入要取款用户的密码!\n");
scanf("%s",d.pw);

printf("请输入要取款的金额!\n");
scanf("%f",&d.money);
  • ユーザー関連情報を保存するために という名前の構造体を作成しますduserm
  • ユーザーの識別番号、ユーザー名、パスワード、出金金額を順に入力します。

5. リクエストをメッセージキューに書き込みます

d.mtype = 3;   //消息类型为3,取款用
msgsnd(g_reqid,&d,sizeof(userm)-sizeof(long),0);
  • メッセージ タイプを 3 に設定し、これが引き出しリクエストであることを示します。
  • msgsndこの関数を使用して、d構造体をリクエスト メッセージ キューに書き込みます。
  • sizeof(userm)-sizeof(long)送信されるメッセージのサイズから、longtype のメッセージ タイプ フィールドのサイズを引いたものを表します。

6. 応答メッセージキューを読み取ります。

RES buf3;
msgrcv(g_resid,&buf3,sizeof(buf3),3,0);  //3类消息,取款用
printf("%s\n",buf3.msg);
  • 応答メッセージを受信するための という名前の構造体を作成しますbuf3RES
  • この関数を使用してmsgrcv、応答メッセージ キューからメッセージを読み取ります。
  • 最初のパラメータはメッセージ キューの識別子です。
  • 2 番目のパラメータは、メッセージを受信するバッファです。
  • 3 番目のパラメータは、受信したメッセージのサイズです。
  • 4 番目のパラメータはメッセージ タイプで、ここでは 3 です。これは、取り消しの応答メッセージを受信することを意味します。
  • 最後のパラメータはフラグで、0 はデフォルトの動作を示します。
  • 受信した応答メッセージを印刷します。

7. 戻る

return;
  • 引き出しビジネス関数の実行を終了し、呼び出した場所に戻ります。

4. お問い合わせ

void Inquire()//查询业务
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    userm e;
    printf("请输入要查询用户的身份号!\n");
    scanf("%s",e.id);
   
    printf("请输入要查询用户的用户名!\n");
    scanf("%s",e.name);
    
    printf("请输入要查询用户的密码!\n");
    scanf("%s",e.pw);
   
    //printf("请输入要查询的金额!\n");
    //scanf("%f",&d.money);
    //往请求消息队列写
    e.mtype = 4;   //消息类型为4,查询用
    msgsnd(g_reqid,&e,sizeof(userm)-sizeof(long),0);
    
    //读应答消息队列
    RES buf4;
    msgrcv(g_resid,&buf4,sizeof(buf4),4,0);  //消息类型为4,查询用
    printf("%s\n",buf4.msg);
    
    return;
}

1. メッセージキューのキー値を作成します。

key_t kid1,kid2;
kid1 = ftok("/home/whs/002/0706",1); //键值
kid2 = ftok("/home/whs/002/0706",2);
  • また、ftokメッセージ キューを作成するための 2 つの異なるキー値を生成する関数も使用します。

2. リクエストメッセージキューをオープンする

g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
if(g_reqid== -1)
{
    
    
    perror("msgget");
    return;
}
  • この関数を使用してmsgget、リクエスト メッセージ キューを開くか作成します。

3. 応答メッセージキューを開く

g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
if(g_resid == -1)
{
    
    
    perror("msgget");
    return;
}
  • また、msggetこの関数を使用して、応答メッセージ キューを開くか作成します。

4. クエリ情報を入力します

userm e;
printf("请输入要查询用户的身份号!\n");
scanf("%s",e.id);

printf("请输入要查询用户的用户名!\n");
scanf("%s",e.name);

printf("请输入要查询用户的密码!\n");
scanf("%s",e.pw);
  • クエリ ユーザーの関連情報を格納するために という名前の構造体を作成しますeuserm
  • ユーザーの ID 番号、ユーザー名、パスワードを順に入力します。

5. リクエストをメッセージキューに書き込みます

e.mtype = 4;   //消息类型为4,查询用
msgsnd(g_reqid,&e,sizeof(userm)-sizeof(long),0);
  • メッセージ タイプを 4 に設定し、これがクエリ要求であることを示します。
  • msgsndこの関数を使用して、e構造体をリクエスト メッセージ キューに書き込みます。
  • sizeof(userm)-sizeof(long)送信されるメッセージのサイズから、longtype のメッセージ タイプ フィールドのサイズを引いたものを表します。

6. 応答メッセージキューを読み取ります。

RES buf4;
msgrcv(g_resid,&buf4,sizeof(buf4),4,0);  //消息类型为4,查询用
printf("%s\n",buf4.msg);
  • 応答メッセージを受信するための という名前の構造体を作成しますbuf4RES
  • この関数を使用してmsgrcv、応答メッセージ キューからメッセージを読み取ります。
  • 最初のパラメータはメッセージ キューの識別子です。
  • 2 番目のパラメータは、メッセージを受信するバッファです。
  • 3 番目のパラメータは、受信したメッセージのサイズです。
  • 4 番目のパラメーターはメッセージ タイプで、ここでは 4 です。これは、クエリ応答メッセージを受信することを意味します。
  • 最後のパラメータはフラグで、0 はデフォルトの動作を示します。
  • 受信した応答メッセージを印刷します。

7. 戻る

return;
  • クエリ ビジネス関数の実行を終了し、呼び出された場所に戻ります。

5. 転送

void Transfer()//转账业务
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    userm f1,f2;
    printf("请输入转账用户的身份号!\n");
    scanf("%s",f1.id);
   
    printf("请输入转账用户的用户名!\n");
    scanf("%s",f1.name);
    
    printf("请输入转账用户的密码!\n");
    scanf("%s",f1.pw);
   
    printf("请输入要转账的金额!\n");
    scanf("%f",&f1.money);
    
    printf("请输入被转账用户的身份号!\n");
    scanf("%s",f2.id);
    //往请求消息队列写
    f1.mtype = 5;   //消息类型为5,转账用,第一条消息,转账用户用
    msgsnd(g_reqid,&f1,sizeof(userm)-sizeof(long),0);
    f2.mtype = 55;   //消息类型为55,转账用,第二条消息,被转账用户用
    msgsnd(g_reqid,&f2,sizeof(userm)-sizeof(long),0);
    //读应答消息队列
    RES buf3;
    msgrcv(g_resid,&buf3,sizeof(buf3),5,0);  //5类消息,转账用
    printf("%s\n",buf3.msg);
    
    
    RES buf4;
    msgrcv(g_resid,&buf4,sizeof(buf4),55,0);  //55类消息,转账用
    printf("%s\n",buf4.msg);
    return;
}

1. メッセージキューのキー値を作成します。

key_t kid1,kid2;
kid1 = ftok("/home/whs/002/0706",1); //键值
kid2 = ftok("/home/whs/002/0706",2);
  • また、ftokメッセージ キューを作成するための 2 つの異なるキー値を生成する関数も使用します。

2. リクエストメッセージキューをオープンする

g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
if(g_reqid== -1)
{
    
    
    perror("msgget");
    return;
}
  • この関数を使用してmsgget、リクエスト メッセージ キューを開くか作成します。

3. 応答メッセージキューを開く

g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
if(g_resid == -1)
{
    
    
    perror("msgget");
    return;
}
  • また、msggetこの関数を使用して、応答メッセージ キューを開くか作成します。

4. 転送ユーザー情報を入力

userm f1,f2;
printf("请输入转账用户的身份号!\n");
scanf("%s",f1.id);

printf("请输入转账用户的用户名!\n");
scanf("%s",f1.name);

printf("请输入转账用户的密码!\n");
scanf("%s",f1.pw);

printf("请输入要转账的金额!\n");
scanf("%f",&f1.money);
  • および という名前の2 つの構造を作成し、転送するユーザーと転送されるユーザーに関する情報をそれぞれ保存しますf1f2userm
  • 送金ユーザーの識別番号、ユーザー名、パスワード、送金金額を順に入力します。

5. リクエストをメッセージキューに書き込みます

f1.mtype = 5;   //消息类型为5,转账用,第一条消息,转账用户用
msgsnd(g_reqid,&f1,sizeof(userm)-sizeof(long),0);
f2.mtype = 55;   //消息类型为55,转账用,第二条消息,被转账用户用
msgsnd(g_reqid,&f2,sizeof(userm)-sizeof(long),0);
  • メッセージ タイプを 5 と 55 に設定し、これらが転送要求の 2 つのメッセージであることを示します。
  • msgsndこの関数を使用して、f1およびf2構造体をそれぞれリクエスト メッセージ キューに書き込みます。
  • sizeof(userm)-sizeof(long)送信されるメッセージのサイズから、longtype のメッセージ タイプ フィールドのサイズを引いたものを表します。

6. 応答メッセージキューを読み取ります。

RES buf3;
msgrcv(g_resid,&buf3,sizeof(buf3),5,0);  //5类消息,转账用
printf("%s\n",buf3.msg);


RES buf4;
msgrcv(g_resid,&buf4,sizeof(buf4),55,0);  //55类消息,转账用
printf("%s\n",buf4.msg);
  • 応答メッセージを受信するために、 および という名前の2 つの構造体を作成しますbuf3buf4RES
  • この関数を使用してmsgrcv、応答メッセージ キューからメッセージを読み取ります。
  • 最初のパラメータはメッセージ キューの識別子です。
  • 2 番目のパラメータは、メッセージを受信するバッファです。
  • 3 番目のパラメータは、受信したメッセージのサイズです。
  • 4 番目のパラメータはメッセージ タイプで、ここではそれぞれ 5 と 55 で、転送を受信するための応答メッセージを示します。
  • 最後のパラメータはフラグで、0 はデフォルトの動作を示します。
  • 受信した応答メッセージを印刷します。

7. 戻る

return;
  • 転送ビジネス関数の実行を終了し、呼び出された場所に戻ります。

6. キャンセル

void Logout()
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    userm b;
    printf("请输入要注销用户的身份号!\n");
    scanf("%s",b.id);
   
    printf("请输入要注销用户的用户名!\n");
    scanf("%s",b.name);
    
    printf("请输入要注销用户的密码!\n");
    scanf("%s",b.pw);
   
    printf("请输入要注销用户的余额!\n");
    scanf("%f",&b.money);
    //往请求消息队列写
    b.mtype = 6;   //消息类型为6,注销用
    msgsnd(g_reqid,&b,sizeof(userm)-sizeof(long),0);
    
    //读应答消息队列
    RES buf1;
    msgrcv(g_resid,&buf1,sizeof(buf1),6,0);  //6类消息,注销用
    printf("%s\n",buf1.msg);
    
    return;
}

1. メッセージキューのキー値を作成します。

key_t kid1,kid2;
kid1 = ftok("/home/whs/002/0706",1); //键值
kid2 = ftok("/home/whs/002/0706",2);
  • また、ftokメッセージ キューを作成するための 2 つの異なるキー値を生成する関数も使用します。

2. リクエストメッセージキューをオープンする

g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
if(g_reqid== -1)
{
    
    
    perror("msgget");
    return;
}
  • この関数を使用してmsgget、リクエスト メッセージ キューを開くか作成します。

3. 応答メッセージキューを開く

g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
if(g_resid == -1)
{
    
    
    perror("msgget");
    return;
}
  • また、msggetこの関数を使用して、応答メッセージ キューを開くか作成します。

4. ログアウトユーザー情報を入力します

userm b;
printf("请输入要注销用户的身份号!\n");
scanf("%s",b.id);

printf("请输入要注销用户的用户名!\n");
scanf("%s",b.name);

printf("请输入要注销用户的密码!\n");
scanf("%s",b.pw);

printf("请输入要注销用户的余额!\n");
scanf("%f",&b.money);
  • ログアウトしたユーザーに関する情報を保存するbために名前を付けた構造体を作成します。userm
  • ログアウトするユーザーの識別番号、ユーザー名、パスワード、残高を順に入力します。

5. リクエストをメッセージキューに書き込みます

b.mtype = 6;   //消息类型为6,注销用
msgsnd(g_reqid,&b,sizeof(userm)-sizeof(long),0);
  • メッセージ タイプを 6 に設定し、これがログアウト要求メッセージであることを示します。
  • msgsndこの関数を使用して、b構造体をリクエスト メッセージ キューに書き込みます。
  • sizeof(userm)-sizeof(long)送信されるメッセージのサイズから、longtype のメッセージ タイプ フィールドのサイズを引いたものを表します。

6. 応答メッセージキューを読み取ります。

RES buf1;
msgrcv(g_resid,&buf1,sizeof(buf1),6,0);  //6类消息,注销用
printf("%s\n",buf1.msg);
  • 応答メッセージを受信するbuf1ための名前付きの構造体を作成します。RES
  • この関数を使用してmsgrcv、応答メッセージ キューからメッセージを読み取ります。
  • 最初のパラメータはメッセージ キューの識別子です。
  • 2 番目のパラメータは、メッセージを受信するバッファです。
  • 3 番目のパラメータは、受信したメッセージのサイズです。
  • 4 番目のパラメータはメッセージ タイプで、ここでは 6 です。これは、ログアウト応答メッセージを受信することを意味します。
  • 最後のパラメータはフラグで、0 はデフォルトの動作を示します。
  • 受信した応答メッセージを印刷します。

7. 戻る

return;
  • ログアウトユーザービジネス関数の実行を終了し、呼び出された場所に戻ります。

コード全体

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int g_reqid; //作为请求的消息队列的返回id
int g_resid;  //作为应答消息队列的返回id
typedef struct msgbuf{
    
    
    long mtype;         //消息类型
    char id[100];       //账户
    char name[256];     //用户名
    char pw[9];        //密码
    float money;       //银行卡余额
}userm;
typedef struct tag_OpenRespond{
    
    
  long   type;
  char   id[100];      //账户
  char   msg[256];
  float  money;       //银行卡余额
}RES;                 //让客户端从应答消息队列读到的反馈存到这里
void menu();
void Account();//开户
void Deposit();//存款
void withdrawal();//取款
void Inquire();//查询
void Transfer();//转账
void Logout();//注销
int main()
{
    
    
    while(1)
    {
    
    
        menu();
        int a;
        printf("请输入要执行的操作!\n");
        scanf("%d",&a);
        switch(a)
          {
    
    
            case 1:Account();break;//开户
            case 2:Deposit();break;//存款
            case 3:withdrawal();break;//取款
            case 4:Inquire();break;//查询
            case 5:Transfer();break;//转账
            case 6:Logout();break;//注销
            case 7:
                return 0;
            
        }
    }
}
void Account()
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    
    userm a;
    printf("请输入要注册的身份号!\n");
    scanf("%s",a.id);
   
    printf("请输入要注册的用户名!\n");
    scanf("%s",a.name);
    
    printf("请输入要注册的密码!\n");
    scanf("%s",a.pw);
   
    printf("请输入要注册的余额!\n");
    scanf("%f",&a.money);
    //往请求消息队列写
    a.mtype = 1;   //消息类型为1,开户用
    msgsnd(g_reqid,&a,sizeof(userm)-sizeof(long),0);
    
    //读应答消息队列
    RES buf;
    msgrcv(g_resid,&buf,sizeof(buf),1,0);  //1类消息,开户用
    printf("%s\n",buf.msg);
    
    return;
    
}
void Logout()
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    userm b;
    printf("请输入要注销用户的身份号!\n");
    scanf("%s",b.id);
   
    printf("请输入要注销用户的用户名!\n");
    scanf("%s",b.name);
    
    printf("请输入要注销用户的密码!\n");
    scanf("%s",b.pw);
   
    printf("请输入要注销用户的余额!\n");
    scanf("%f",&b.money);
    //往请求消息队列写
    b.mtype = 6;   //消息类型为6,注销用
    msgsnd(g_reqid,&b,sizeof(userm)-sizeof(long),0);
    
    //读应答消息队列
    RES buf1;
    msgrcv(g_resid,&buf1,sizeof(buf1),6,0);  //6类消息,注销用
    printf("%s\n",buf1.msg);
    
    return;
}
void Deposit()//存款业务
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    userm c;
    printf("请输入要存款用户的身份号!\n");
    scanf("%s",c.id);
   
    printf("请输入要存款用户的用户名!\n");
    scanf("%s",c.name);
    
    printf("请输入要存款用户的密码!\n");
    scanf("%s",c.pw);
   
    printf("请输入要存款的金额!\n");
    scanf("%f",&c.money);
    //往请求消息队列写
    c.mtype = 2;   //消息类型为2,存款用
    msgsnd(g_reqid,&c,sizeof(userm)-sizeof(long),0);
    
    //读应答消息队列
    RES buf2;
    msgrcv(g_resid,&buf2,sizeof(buf2),2,0);  //2类消息,存款用
    printf("%s\n",buf2.msg);
    
    return;
}
void withdrawal()//取款业务
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    userm d;
    printf("请输入要取款用户的身份号!\n");
    scanf("%s",d.id);
   
    printf("请输入要取款用户的用户名!\n");
    scanf("%s",d.name);
    
    printf("请输入要取款用户的密码!\n");
    scanf("%s",d.pw);
   
    printf("请输入要取款的金额!\n");
    scanf("%f",&d.money);
    //往请求消息队列写
    d.mtype = 3;   //消息类型为3,取款用
    msgsnd(g_reqid,&d,sizeof(userm)-sizeof(long),0);
    
    //读应答消息队列
    RES buf3;
    msgrcv(g_resid,&buf3,sizeof(buf3),3,0);  //3类消息,取款用
    printf("%s\n",buf3.msg);
    
    return;
}
void Inquire()
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    userm e;
    printf("请输入要查询用户的身份号!\n");
    scanf("%s",e.id);
   
    printf("请输入要查询用户的用户名!\n");
    scanf("%s",e.name);
    
    printf("请输入要查询用户的密码!\n");
    scanf("%s",e.pw);
   
    //printf("请输入要查询的金额!\n");
    //scanf("%f",&d.money);
    //往请求消息队列写
    e.mtype = 4;   //消息类型为4,查询用
    msgsnd(g_reqid,&e,sizeof(userm)-sizeof(long),0);
    
    //读应答消息队列
    RES buf4;
    msgrcv(g_resid,&buf4,sizeof(buf4),4,0);  //消息类型为4,查询用
    printf("%s\n",buf4.msg);
    
    return;
}
void Transfer()//转账业务
{
    
    
    key_t kid1,kid2;
   
    kid1 = ftok("/home/whs/002/0706",1); //键值
    kid2 = ftok("/home/whs/002/0706",2);
    g_reqid = msgget(kid1,IPC_CREAT|0644); //打开请求消息队列
    if(g_reqid== -1)
    {
    
    
        perror("msgget");
        return;
    }
 
    g_resid =msgget(kid2,IPC_CREAT|0644); //打开应答消息队列
    if(g_resid == -1)
    {
    
    
        perror("msgget");
        return;
    }
    userm f1,f2;
    printf("请输入转账用户的身份号!\n");
    scanf("%s",f1.id);
   
    printf("请输入转账用户的用户名!\n");
    scanf("%s",f1.name);
    
    printf("请输入转账用户的密码!\n");
    scanf("%s",f1.pw);
   
    printf("请输入要转账的金额!\n");
    scanf("%f",&f1.money);
    
    printf("请输入被转账用户的身份号!\n");
    scanf("%s",f2.id);
    //往请求消息队列写
    f1.mtype = 5;   //消息类型为5,转账用,第一条消息,转账用户用
    msgsnd(g_reqid,&f1,sizeof(userm)-sizeof(long),0);
    f2.mtype = 55;   //消息类型为55,转账用,第二条消息,被转账用户用
    msgsnd(g_reqid,&f2,sizeof(userm)-sizeof(long),0);
    //读应答消息队列
    RES buf3;
    msgrcv(g_resid,&buf3,sizeof(buf3),5,0);  //5类消息,转账用
    printf("%s\n",buf3.msg);
    
    
    RES buf4;
    msgrcv(g_resid,&buf4,sizeof(buf4),55,0);  //55类消息,转账用
    printf("%s\n",buf4.msg);
    return;
}
void menu()
{
    
    
    printf("********欢迎来到小黑银行!************\n");
    printf("**************1.开户******************\n");
    printf("**************2.存款******************\n");
    printf("**************3.取款******************\n");
    printf("**************4.查询******************\n");
    printf("**************5.转账******************\n");
    printf("**************6.销户******************\n");
    printf("**************7.退出******************\n");
    
}

おすすめ

転載: blog.csdn.net/Goforyouqp/article/details/132892369