• linux 下用C实现 ATM 自动取款机功能 (进程间通信)


    直接先上图:

    项目需求:

    主要分为两人大模块:
        
        客户端
            1、进入时的功能开户、销户、登录、解锁
                开户:输入姓名、身份证号、设置密码,如果开户成功,则服务器上保存一个账号信号(一个账号存一个文件,文件名建议是账号)。
                销户:输入帐号、密码,服务器询问是否确认销户,如果确认则服务器删除帐号文件,并记录帐号。(我没实现)
                登录:输入账号、密码,三次错误账号锁定。
                解锁:输入账号、身份证号解锁。
            2、登录成功:存钱、取钱、转账、查询、修改密码
                存钱:输入存钱金额
                取钱:输入取钱金额
                转账:目标帐号和要转的金额
                查询:不需要输入数据
                修改密码:原密码和新密码
        服务器
            如果识别功能:根据消息的类型识别客户端请求的功能。
            开启服务各项功能的子进程
                各进程按照消息类型接收消息
    
    

    打开2个终端,一个编译所有文件

    然后运行server(服务端)

    另一个终端运行client(客户端)

    切记不要关闭服务端。

    接下来在客户端进行操作。

    1、开户(客户端)

    (服务端)会输出相关信息

    2、销户

    (客户端)

    (服务端)

    3、登录

    (客户端)

    (服务端)

    登录后(子功能)

    具体就不在列举了,下面提供部分源码,具体请移步码云GitHub

    server.c

     1 #include <stdio.h>
     2 #include <unistd.h>
     3 #include <signal.h>
     4 #include <sys/ipc.h>
     5 #include <sys/msg.h>
     6 #include <sys/wait.h>
     7 #include "struct.h"
     8 #include "tools.h"
     9 
    10 static int msgid_ctos;
    11 static int msgid_stoc;
    12 static pid_t sub_pid[9];
    13 
    14 void sigint(int sig)
    15 {
    16     msgctl(msgid_ctos,IPC_RMID,NULL);
    17     msgctl(msgid_stoc,IPC_RMID,NULL);
    18     
    19     int i;
    20     for(i=0; i<9; i++)
    21     {
    22         kill(sub_pid[i],SIGKILL);
    23     }
    24 }
    25 
    26 int main()
    27 {
    28     signal(SIGINT,sigint);
    29 
    30     msgctl(msgid_ctos,IPC_RMID,NULL);
    31     msgctl(msgid_stoc,IPC_RMID,NULL);
    32 
    33     msgid_ctos = msgget(ftok(".",100),IPC_CREAT|IPC_EXCL|0644);
    34     msgid_stoc = msgget(ftok(".",200),IPC_CREAT|IPC_EXCL|0644);
    35     
    36     sub_pid[0] = vfork();
    37     if(0 == sub_pid[0])
    38     {
    39         execl("login","login",NULL);
    40         printf("登陆子进程创建成功...
    ");
    41     }
    42 
    43     sub_pid[1] = vfork();
    44     if(0 == sub_pid[1])
    45     {
    46         execl("open","open",NULL);
    47         printf("开户子进程创建成功...
    ");
    48     }
    49     sub_pid[2] = vfork();
    50     if(0 == sub_pid[2])
    51     {
    52         execl("save","save",NULL);
    53     }
    54     
    55     sub_pid[3] = vfork();
    56     if(0 == sub_pid[3])
    57     {
    58         execl("take","take",NULL);
    59     }
    60     
    61     sub_pid[4] = vfork();
    62     if(0 == sub_pid[4])
    63     {
    64         execl("transf","transf",NULL);
    65     }
    66 
    67     sub_pid[5] = vfork();
    68     if(0 == sub_pid[5])
    69     {
    70         execl("select","select",NULL);
    71     }
    72 
    73 //login open save take transf select change destory unlock
    74 
    75     sub_pid[6] = vfork();
    76     if(0 == sub_pid[6])
    77     {
    78         execl("change","change",NULL);
    79     }    
    80 
    81     sub_pid[7] = vfork();
    82     if(0 == sub_pid[7])
    83     {
    84         execl("destory","destory",NULL);
    85     }
    86 
    87     sub_pid[8] = vfork();
    88     if(0 == sub_pid[8])
    89     {
    90         execl("unlock","unlock",NULL);
    91     }
    92 
    93     //pause();
    94     while(-1 != wait(NULL));
    95 }
     1 #include <stdio.h>
     2 #include <unistd.h>
     3 #include <signal.h>
     4 #include <sys/ipc.h>
     5 #include <sys/msg.h>
     6 #include <sys/wait.h>
     7 #include "struct.h"
     8 #include "tools.h"
     9 
    10 static int msgid_ctos;
    11 static int msgid_stoc;
    12 static pid_t sub_pid[9];
    13 
    14 void sigint(int sig)
    15 {
    16     msgctl(msgid_ctos,IPC_RMID,NULL);
    17     msgctl(msgid_stoc,IPC_RMID,NULL);
    18     
    19     int i;
    20     for(i=0; i<9; i++)
    21     {
    22         kill(sub_pid[i],SIGKILL);
    23     }
    24 }
    25 
    26 int main()
    27 {
    28     signal(SIGINT,sigint);
    29 
    30     msgctl(msgid_ctos,IPC_RMID,NULL);
    31     msgctl(msgid_stoc,IPC_RMID,NULL);
    32 
    33     msgid_ctos = msgget(ftok(".",100),IPC_CREAT|IPC_EXCL|0644);
    34     msgid_stoc = msgget(ftok(".",200),IPC_CREAT|IPC_EXCL|0644);
    35     
    36     sub_pid[0] = vfork();
    37     if(0 == sub_pid[0])
    38     {
    39         execl("login","login",NULL);
    40         printf("登陆子进程创建成功...
    ");
    41     }
    42 
    43     sub_pid[1] = vfork();
    44     if(0 == sub_pid[1])
    45     {
    46         execl("open","open",NULL);
    47         printf("开户子进程创建成功...
    ");
    48     }
    49     sub_pid[2] = vfork();
    50     if(0 == sub_pid[2])
    51     {
    52         execl("save","save",NULL);
    53     }
    54     
    55     sub_pid[3] = vfork();
    56     if(0 == sub_pid[3])
    57     {
    58         execl("take","take",NULL);
    59     }
    60     
    61     sub_pid[4] = vfork();
    62     if(0 == sub_pid[4])
    63     {
    64         execl("transf","transf",NULL);
    65     }
    66 
    67     sub_pid[5] = vfork();
    68     if(0 == sub_pid[5])
    69     {
    70         execl("select","select",NULL);
    71     }
    72 
    73 //login open save take transf select change destory unlock
    74 
    75     sub_pid[6] = vfork();
    76     if(0 == sub_pid[6])
    77     {
    78         execl("change","change",NULL);
    79     }    
    80 
    81     sub_pid[7] = vfork();
    82     if(0 == sub_pid[7])
    83     {
    84         execl("destory","destory",NULL);
    85     }
    86 
    87     sub_pid[8] = vfork();
    88     if(0 == sub_pid[8])
    89     {
    90         execl("unlock","unlock",NULL);
    91     }
    92 
    93     //pause();
    94     while(-1 != wait(NULL));
    95 }

    client.c

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <unistd.h>
      5 #include <sys/types.h>
      6 #include <sys/ipc.h>
      7 #include <sys/msg.h>
      8 #include <sys/stat.h>
      9 #include <stdlib.h>
     10 #include <fcntl.h>
     11 #include "struct.h"
     12 #include "tools.h"
     13 //#include "msg_queue.c"
     14 
     15 static long online = 0;
     16 static int lock = 0;
     17 
     18 int msgid_ctos;
     19 int msgid_stoc;
     20 
     21 int init();
     22 void open_acc();
     23 void destory();
     24 void login();
     25 void unlock();
     26 void user_menu(void);
     27 void menu(void);
     28 void save();
     29 void take();
     30 void transf();
     31 void select_money();
     32 void change_pw();
     33 
     34 int main()
     35 {
     36     init();
     37     menu();
     38 }
     39 
     40 int init()
     41 {
     42     //msgctl(msgid_ctos,IPC_RMID,NULL);
     43     // 创建消息队列
     44     msgid_ctos = msgget(ftok(".",100),0);
     45     if(0 > msgid_ctos)
     46     {
     47         perror("msgget");
     48         return -1;
     49     }
     50     msgid_stoc = msgget(ftok(".",200),0);
     51     if(0 > msgid_stoc)
     52     {
     53         perror("msgget");
     54         return -1;
     55     }
     56     return 0;
     57 }
     58 
     59 void login()//0
     60 {
     61     if(lock >= 3)
     62     {
     63         printf("您已被锁定,请解锁
    ");
     64         getchar();
     65         return;
     66     }
     67     Account acc = {};
     68     Msg msg = {110};
     69     printf("请输入帐号:");
     70     scanf("%ld",&acc.user);
     71     getchar();
     72     printf("请输入密码:");
     73     get_str(acc.pw,20);
     74     msg.acc = acc;
     75     msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
     76 
     77     Msg msg2 = {};
     78     // 接收消息
     79     msgrcv(msgid_stoc,&msg2,sizeof(Msg),220,MSG_NOERROR);
     80     
     81     if(acc.user == msg2.acc.user)
     82     {
     83         online = acc.user;
     84         printf("%ld,登陆成功
    ",online);
     85         getch();
     86         user_menu();
     87     }
     88     else
     89     {    
     90         lock++;    
     91         printf("帐号或密码错误
    ");
     92         getch();
     93     }
     94 }
     95 
     96 void open_acc()//1
     97 {
     98 
     99     Account acc = {};
    100     Msg msg = {111};
    101     printf("请输入姓名:");
    102     get_str(acc.name,20);
    103     printf("请输入身份证:");
    104     get_str(acc.id,20);
    105     printf("请输入密码:");
    106     get_str(acc.pw,20);
    107     msg.acc = acc;
    108     //printf("msg:%s
    ",msg.acc.name);
    109     msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
    110 
    111     Msg msg2 = {};
    112     // 接收消息
    113     msgrcv(msgid_stoc,&msg2,sizeof(Msg),221,MSG_NOERROR);
    114     printf("msg2:%s,acc:%s
    ",msg2.acc.name,acc.name);
    115     if(strcmp(acc.name,msg2.acc.name) == 0)
    116     {
    117         //printf("%s
    ",msg2.acc.name);
    118         //printf("%s
    ",msg2.acc.id);
    119         printf("帐号:%ld,开户成功
    ",msg2.acc.user);
    120     }
    121     else
    122     {        
    123         printf("开户失败
    ");
    124     }
    125     getch();
    126 }
    127 
    128 void save()//2
    129 {
    130     Account acc = {};
    131     Msg msg = {112};
    132     //printf("当前用户:%ld
    ",online);
    133     printf("请输入存款金额:");
    134     scanf("%lf",&acc.money);
    135     getchar();
    136     acc.user = online;    
    137     msg.acc = acc;
    138     msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
    139 
    140     Msg msg2 = {};
    141     // 接收消息
    142     msgrcv(msgid_stoc,&msg2,sizeof(Msg),222,MSG_NOERROR);
    143     if(msg2.acc.user == online)
    144     {
    145         printf("存钱成功
    ");
    146     }
    147     else
    148     {
    149         printf("存钱失败
    ");
    150     }
    151     getch();
    152 }
    153 
    154 void take()//3
    155 {
    156     Account acc = {};
    157     Msg msg = {113};
    158     printf("请输入取款金额:");
    159     scanf("%lf",&acc.money);
    160     getchar();
    161     acc.user = online;    
    162     msg.acc = acc;
    163     msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
    164 
    165     Msg msg2 = {};
    166     // 接收消息
    167     msgrcv(msgid_stoc,&msg2,sizeof(Msg),223,MSG_NOERROR);
    168     if(msg2.acc.user == online)
    169     {
    170         printf("取钱成功
    ");
    171     }
    172     else if(msg2.acc.user == online + 2)
    173     {
    174         printf("余额不足,请充值
    ");
    175     }
    176     else
    177     {
    178         printf("取钱失败
    ");
    179     }
    180     getch();
    181 }
    182 void transf()//4
    183 {
    184     Account acc = {};
    185     Msg msg = {114};
    186     printf("请输入转帐金额:");
    187     scanf("%lf",&acc.money);
    188     getchar();
    189     acc.user = online;    
    190     msg.acc = acc;
    191     msg.flag = 0;
    192     msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
    193 
    194     Msg msg2 = {};
    195     // 接收消息
    196     msgrcv(msgid_stoc,&msg2,sizeof(Msg),224,MSG_NOERROR);
    197     if(msg2.flag == 0)
    198     {
    199         printf("请输入要转帐的帐号:");
    200         scanf("%ld",&acc.user);
    201         getchar();
    202         msg.acc = acc;
    203         msg.flag = 1;
    204     msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
    205         
    206         // 接收消息
    207         msgrcv(msgid_stoc,&msg2,sizeof(Msg),224,MSG_NOERROR);
    208         
    209         if(msg2.flag == 2)
    210         {
    211             printf("转帐成功
    ");
    212         }
    213         else
    214         {
    215             printf("转帐失败
    ");
    216         }
    217             
    218     }
    219     else
    220     {
    221         printf("余额不足,请充值
    ");
    222     }
    223     getch();
    224 }
    225 void select_money()//5
    226 {
    227     Account acc = {};
    228     Msg msg = {115};
    229     acc.user = online;    
    230     msg.acc = acc;
    231     msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
    232 
    233     Msg msg2 = {};
    234     // 接收消息
    235     msgrcv(msgid_stoc,&msg2,sizeof(Msg),225,MSG_NOERROR);
    236     if(msg2.acc.user == online)
    237     {
    238         printf("余额:%.2lf
    ",msg2.acc.money);
    239     }
    240     else
    241     {
    242         printf("查询失败
    ");
    243     }
    244     getch();
    245 }
    246 void change_pw()//6
    247 {
    248     Account acc = {};
    249     Msg msg = {116};
    250     printf("请输入新密码:");
    251     get_str(acc.pw,20);
    252     acc.user = online;    
    253     msg.acc = acc;
    254     msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
    255 
    256     Msg msg2 = {};
    257     // 接收消息
    258     msgrcv(msgid_stoc,&msg2,sizeof(Msg),226,MSG_NOERROR);
    259     if(msg2.acc.user == online)
    260     {
    261         printf("改密成功
    ");
    262     }
    263     else
    264     {
    265         printf("改密失败
    ");
    266     }
    267     getch();
    268 }
    269 
    270 void destory()//7
    271 {
    272     Account acc = {};
    273     Msg msg = {117};
    274     printf("请输入销户帐号:");
    275     scanf("%ld",&acc.user);
    276     getchar();
    277     printf("请输入姓名:");
    278     get_str(acc.name,20);
    279     printf("请输入身份证:");
    280     get_str(acc.id,20);
    281     msg.acc = acc;
    282     msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
    283 
    284     Msg msg2 = {};
    285     // 接收消息
    286     msgrcv(msgid_stoc,&msg2,sizeof(Msg),227,MSG_NOERROR);
    287     if(msg2.acc.user == 0)
    288     {
    289         printf("销户成功
    ");
    290     }
    291     else if(msg2.acc.user == 1)
    292     {
    293         printf("相关信息错误
    ");
    294     }
    295     else if(msg2.acc.user == 2)
    296     {
    297         printf("帐号不存在
    ");
    298     }
    299     getch();
    300 }
    301 
    302 void unlock()//8
    303 {
    304     if(lock < 3)
    305     {
    306         printf("您没有被锁定,sorry
    ");
    307         getchar();
    308         return;
    309     }
    310     Account acc = {};
    311     Msg msg = {118};
    312     printf("请输入帐号:");
    313     scanf("%ld",&acc.user);
    314     getchar();
    315     printf("请输入姓名:");
    316     get_str(acc.name,20);
    317     printf("请输入身份证:");
    318     get_str(acc.id,20);
    319     msg.acc = acc;
    320     msgsnd(msgid_ctos,&msg,sizeof(Msg)-sizeof(msg.type),0);
    321 
    322     //printf("消息已发送到队列
    ");
    323 
    324     Msg msg2 = {};
    325     // 接收消息
    326     msgrcv(msgid_stoc,&msg2,sizeof(Msg),228,MSG_NOERROR);
    327     
    328     //printf("已接收到队列的消息
    ");
    329     printf("in:%ld,back:%ld
    ",acc.user,msg2.acc.user);
    330     
    331     if(acc.user == msg2.acc.user)
    332     {
    333         printf("%ld,解锁成功
    ",acc.user);
    334         lock = 0;
    335         online = acc.user;
    336         change_pw();
    337     }
    338     else
    339     {    
    340         printf("相关信息错误
    ");
    341         getch();
    342     }
    343 
    344 /*    long user = 0;
    345     char id[20] = {};
    346     char name[20] = {};
    347     printf("请输入要解锁的帐号:");
    348     scanf("%ld",&user);
    349     getchar();
    350 
    351     char path[50] = "./data/";
    352     char ex[8] = ".dat";
    353     sprintf(path,"%s%ld%s",path,user,ex);
    354 
    355     if(0 == access(path,F_OK))
    356     {
    357         Account buf = {};
    358         int fd = open(path,O_RDWR);
    359         if(0 != read(fd,&buf,sizeof(Account)))
    360         {
    361             char name[20] = {};
    362             char id[20] = {};
    363             printf("请输入此帐号开户姓名:");
    364             get_str(name,20);
    365             printf("请输入此帐号开户身份证:");
    366             get_str(id,20);
    367 
    368             if(strcmp(name,buf.name) == 0 && strcmp(id,buf.id) == 0)
    369             {
    370                 online = user;
    371                 change_pw();
    372                 lock = 0;
    373             }
    374             else
    375             {
    376                 printf("输入信息有误
    ");
    377                 close(fd);
    378                 getch();
    379             }
    380         }
    381         else
    382         {
    383             printf("读取信息失败
    ");
    384             getch();
    385         }
    386     }
    387     else
    388     {
    389         printf("此帐号不存在
    ");
    390         getch();
    391     }
    392 */
    393 }
    394 
    395 void user_menu(void)
    396 {
    397     while(1)
    398     {
    399         system("clear");
    400         printf("---  银行  ---
    ");
    401         printf("1、  存钱
    ");
    402         printf("2、  取钱
    ");
    403         printf("3、  转帐
    ");
    404         printf("4、  查询
    ");
    405         printf("5、  改密
    ");
    406         printf("0、  返回
    ");
    407         switch(get_cmd('0','5'))
    408         {
    409             case '1':save(); break;
    410             case '2':take(); break;
    411             case '3':transf(); break;
    412             case '4':select_money(); break;
    413             case '5':change_pw();break;
    414             case '0':return;
    415         }
    416     }
    417 }
    418 
    419 void menu(void)
    420 {
    421     while(1)
    422     {
    423         system("clear");
    424         printf("---  银行  ---
    ");
    425         printf("1、  开户
    ");
    426         printf("2、  销户
    ");
    427         printf("3、  登陆
    ");
    428         printf("4、  解锁
    ");
    429         printf("0、  退出
    ");
    430         switch(get_cmd('0','4'))
    431         {
    432             case '1':open_acc(); break;
    433             case '2':destory(); break;
    434             case '3':login(); break;
    435             case '4':unlock(); break;
    436             case '0':return;
    437         }
    438     }
    439 }
  • 相关阅读:
    nodejs访问mysql数据库工具ali-mysql-client
    谈谈数据监听observable的实现
    【开源】分享一个前后端分离方案-前端angularjs+requirejs+dhtmlx 后端asp.net webapi
    我的微型工作流引擎-办公应用实战
    我的微型工作流引擎-功能解析及API设计
    我的微型工作流引擎设计
    给Asp.Net MVC及WebApi添加路由优先级
    通用的业务编码规则设计实现
    快速开发之代码生成器(asp.net mvc4 + easyui + knockoutjs)
    利用CSS预处理技术实现项目换肤功能(less css + asp.net mvc4.0 bundle)
  • 原文地址:https://www.cnblogs.com/ikaros-521/p/11290972.html
Copyright © 2020-2023  润新知