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

时间:2024-02-22 07:39:05

直接先上图:

项目需求:

主要分为两人大模块:
    
    客户端
        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("登陆子进程创建成功...\n");
41     }
42 
43     sub_pid[1] = vfork();
44     if(0 == sub_pid[1])
45     {
46         execl("open","open",NULL);
47         printf("开户子进程创建成功...\n");
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("登陆子进程创建成功...\n");
41     }
42 
43     sub_pid[1] = vfork();
44     if(0 == sub_pid[1])
45     {
46         execl("open","open",NULL);
47         printf("开户子进程创建成功...\n");
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("您已被锁定,请解锁\n");
 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,登陆成功\n",online);
 85         getch();
 86         user_menu();
 87     }
 88     else
 89     {    
 90         lock++;    
 91         printf("帐号或密码错误\n");
 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\n",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\n",msg2.acc.name,acc.name);
115     if(strcmp(acc.name,msg2.acc.name) == 0)
116     {
117         //printf("%s\n",msg2.acc.name);
118         //printf("%s\n",msg2.acc.id);
119         printf("帐号:%ld,开户成功\n",msg2.acc.user);
120     }
121     else
122     {        
123         printf("开户失败\n");
124     }
125     getch();
126 }
127 
128 void save()//2
129 {
130     Account acc = {};
131     Msg msg = {112};
132     //printf("当前用户:%ld\n",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("存钱成功\n");
146     }
147     else
148     {
149         printf("存钱失败\n");
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("取钱成功\n");
171     }
172     else if(msg2.acc.user == online + 2)
173     {
174         printf("余额不足,请充值\n");
175     }
176     else
177     {
178         printf("取钱失败\n");
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("转帐成功\n");
212         }
213         else
214         {
215             printf("转帐失败\n");
216         }
217             
218     }
219     else
220     {
221         printf("余额不足,请充值\n");
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\n",msg2.acc.money);
239     }
240     else
241     {
242         printf("查询失败\n");
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("改密成功\n");
262     }
263     else
264     {
265         printf("改密失败\n");
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("销户成功\n");
290     }
291     else if(msg2.acc.user == 1)
292     {
293         printf("相关信息错误\n");
294     }
295     else if(msg2.acc.user == 2)
296     {
297         printf("帐号不存在\n");
298     }
299     getch();
300 }
301 
302 void unlock()//8
303 {
304     if(lock < 3)
305     {
306         printf("您没有被锁定,sorry\n");
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("消息已发送到队列\n");
323 
324     Msg msg2 = {};
325     // 接收消息
326     msgrcv(msgid_stoc,&msg2,sizeof(Msg),228,MSG_NOERROR);
327     
328     //printf("已接收到队列的消息\n");
329     printf("in:%ld,back:%ld\n",acc.user,msg2.acc.user);
330     
331     if(acc.user == msg2.acc.user)
332     {
333         printf("%ld,解锁成功\n",acc.user);
334         lock = 0;
335         online = acc.user;
336         change_pw();
337     }
338     else
339     {    
340         printf("相关信息错误\n");
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("输入信息有误\n");
377                 close(fd);
378                 getch();
379             }
380         }
381         else
382         {
383             printf("读取信息失败\n");
384             getch();
385         }
386     }
387     else
388     {
389         printf("此帐号不存在\n");
390         getch();
391     }
392 */
393 }
394 
395 void user_menu(void)
396 {
397     while(1)
398     {
399         system("clear");
400         printf("---  银行  ---\n");
401         printf("1、  存钱\n");
402         printf("2、  取钱\n");
403         printf("3、  转帐\n");
404         printf("4、  查询\n");
405         printf("5、  改密\n");
406         printf("0、  返回\n");
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("---  银行  ---\n");
425         printf("1、  开户\n");
426         printf("2、  销户\n");
427         printf("3、  登陆\n");
428         printf("4、  解锁\n");
429         printf("0、  退出\n");
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 }