网络版ATM项目的实现——客户端

网络版的ATM实现思路

客户端

  1 #include "customer.h"
  2 
  3 static int sockfd;
  4 
  5 /*int create_msg_queue_c(int key)
  6 {
  7     //创建消息队列
  8     int msgid = msgget(key,IPC_CREAT|0644);
  9     if(0 > msgid)
 10     {
 11         perror("msgget");
 12         return -1;
 13     }
 14     return msgid;
 15 }*/
 16 
 17 void show_menu(void)
 18 {
 19     printf("Welcome to Online Bank !\n");
 20     printf("---------------------\n");
 21     printf("    [1]开户        \n");
 22     printf("    [2]登录        \n");
 23     printf("    [3]解锁        \n");
 24     printf("    [4]销户        \n");
 25     printf("    [5]退出        \n");
 26     printf("---------------------\n");
 27 }
 28 //开户界面
 29 void open_menu(void)
 30 {
 31     
 32     Msg msg = {99};
 33     //得到基本信息
 34     printf("请输入姓名:");
 35     gets(msg.acc.name);
 36     printf("请输入身份证号:");
 37     gets(msg.acc.idcard);
 38     printf("请输入预存金额:");
 39     scanf("%f",&msg.acc.money);
 40     //清空缓冲区
 41     stdin->_IO_read_ptr = stdin->_IO_read_end;
 42     strcpy(msg.acc.password,"123456");
 43     printf("%d\n",msg.acc.account);
 44     //将获得的基本信息发送到服务端
 45     send(sockfd,&msg,sizeof(Msg),0);
 46     //接收服务端传回的信息(账号id)
 47     recv(sockfd,&msg,sizeof(Msg),0);
 48     //perror("msgrcv");
 49     printf("*****您的id是%d,初始密码为123456,账号内的余额为%f*****\n",msg.acc.account,msg.acc.money);
 50     sleep(2);
 51 }
 52 //显示登陆后的功能界面
 53 void func_menu(void)
 54 {
 55     printf("Welcome to Online Bank !\n");
 56     printf("---------------------\n");
 57     printf("    [1]存款        \n");
 58     printf("    [2]取款        \n");
 59     printf("    [3]转账        \n");
 60     printf("    [4]查询        \n");
 61     printf("    [5]修密        \n");
 62     printf("    [6]退出        \n");
 63     printf("---------------------\n");
 64 }
 65 //退出登录
 66 void logout(int id)
 67 {
 68     
 69     Msg msg = {50};
 70     msg.acc.account = id;
 71     send(sockfd,&msg,sizeof(Msg),0);
 72     //接收服务端传回的信息(账号id)
 73     recv(sockfd,&msg,sizeof(Msg),0);
 74     printf("退出成功!\n");
 75     sleep(2);
 76 }
 77 //存钱界面
 78 void save(int id)
 79 {
 80     Msg msg = {5};
 81     msg.acc.account = id;
 82     printf("请输入要存的金额:");
 83     scanf("%f",&msg.acc.money);
 84     //清空缓冲区
 85     stdin->_IO_read_ptr = stdin->_IO_read_end;
 86     //将获得的基本信息发送到服务端
 87     send(sockfd,&msg,sizeof(Msg),0);
 88     //接收服务端传回的信息(账号id)
 89     recv(sockfd,&msg,sizeof(Msg),0);
 90     printf("存款成功!\n");
 91     printf("*****您的id是%d,账号内的余额为%f*****\n",msg.acc.account,msg.acc.money);
 92     sleep(2);
 93 }
 94 //取款界面
 95 void take(int id)
 96 {
 97     Msg msg = {6};
 98     msg.acc.account = id;
 99     printf("请输入要取的金额:");
100     scanf("%f",&msg.acc.money);
101     //清空缓冲区
102     stdin->_IO_read_ptr = stdin->_IO_read_end;
103     //将获得的基本信息发送到服务端
104     send(sockfd,&msg,sizeof(Msg),0);
105     //接收服务端传回的信息(账号id)
106     recv(sockfd,&msg,sizeof(Msg),0);
107     if(-1 == msg.acc.flag)
108     {
109         printf("取款失败!\n");
110         sleep(2);
111     }
112     else
113     {
114         printf("取款成功!\n");
115         printf("*****您的id是%d,账号内的余额为%f*****\n",msg.acc.account,msg.acc.money);
116         sleep(2);
117     }
118 }
119 //转账界面
120 void trans(int id)
121 {
122     Msg msg1 = {7};
123     //Msg msg2 = {17};
124     msg1.acc.account = id;
125     printf("请输入转账对象的id:");
126     scanf("%d",&msg1.acc.target);
127     //清空缓冲区
128     stdin->_IO_read_ptr = stdin->_IO_read_end;
129     printf("请输入要转账的金额:");
130     scanf("%f",&msg1.acc.money);
131     //清空缓冲区
132     stdin->_IO_read_ptr = stdin->_IO_read_end;
133     //将获得的基本信息发送到服务端
134     send(sockfd,&msg1,sizeof(Msg),0);
135     //接收服务端传回的信息(账号id)
136     recv(sockfd,&msg1,sizeof(Msg),0);
137     switch(msg1.acc.flag)
138     {
139         case -1:printf("您的余额不足!\n");sleep(2);break;
140         case -2:printf("转账对象不存在!\n");sleep(2);break;
141         case 0:    printf("转账成功!\n");
142                 printf("*****您的id是%d,账号内的余额为%f*****\n",msg1.acc.account,msg1.acc.money);
143                 sleep(2);break;
144     }
145 }
146 
147 //查询界面
148 void show(int id)
149 {
150     system("clear");
151     Msg msg = {8};
152     msg.acc.account = id;
153     //将获得的基本信息发送到服务端
154     send(sockfd,&msg,sizeof(Msg),0);
155     //接收服务端传回的信息(账号id)
156     recv(sockfd,&msg,sizeof(Msg),0);
157     printf("%s用户您好!\n",msg.acc.name);
158     printf("账号ID:%d\n",msg.acc.account);
159     printf("身份证号:%s\n",msg.acc.idcard);
160     printf("账号余额:%f\n",msg.acc.money);
161     printf("*****按任意键返回*****\n");
162     getchar();    
163 }
164 
165 //修改密码界面
166 void change(int id)
167 {
168     Msg msg = {9};
169     msg.acc.account = id;
170     printf("请输入您的身份账号以用于验证用户信息:");
171     gets(msg.acc.idcard);
172     printf("请输入新密码(6位):");
173     put_pw(msg.acc.password);
174     if(6 != strlen(msg.acc.password))
175     {
176         printf("密码格式不符!\n");
177         sleep(2);
178         return;
179     }
180     else
181     {
182         //将获得的基本信息发送到服务端
183         send(sockfd,&msg,sizeof(Msg),0);
184         //接收服务端传回的信息(账号id)
185         recv(sockfd,&msg,sizeof(Msg),0);
186         if(-1 == msg.acc.flag)
187         {
188             printf("修改失败!\n");
189             sleep(2);
190         }
191         else
192         {
193             printf("修改成功!\n");
194             sleep(2);
195         }
196     }
197 }
198 
199 //副主界面
200 void ano_main(int id)
201 {
202     while(1)
203     {
204         system("clear");
205         func_menu();
206         switch(getch())
207         {
208             case 49:save(id);break;
209             case 50:take(id);break;
210             case 51:trans(id);break;
211             case 52:show(id);break;
212             case 53:change(id);break;
213             case 54:logout(id);return;
214         }
215     }
216 }
217 //加载界面
218 void loading(void)
219 {
220     //system("clear");
221     char buf[103] = {};
222     memset(buf, ' ', sizeof(buf));
223     buf[0] = '[';
224     buf[101] = ']';
225     buf[102] = '\0';
226     int i = 0;
227     char index[6] = "-\\|/\0";
228     while (i <= 99)
229     {
230         buf[i+1] = '>';
231         printf("%s[%d%%][%c]\r",buf,i,index[i%4]);
232         fflush(stdout);//刷新缓冲区
233         usleep(50000);
234         i++;
235     }
236  
237     printf("\n");
238 }
239 //登录界面
240 void login_menu(void)
241 {
242     Msg msg = {2};
243     msg.acc.flag = -1;
244     //获取账号密码
245     printf("请输入账号:");
246     scanf("%d",&msg.acc.account);
247     //清空缓冲区
248     stdin->_IO_read_ptr = stdin->_IO_read_end;
249     printf("请输入密码:");
250     put_pw(msg.acc.password);
251     //将获得的基本信息发送到服务端
252     send(sockfd,&msg,sizeof(Msg),0);
253     //接收服务端传回的信息(账号id)
254     recv(sockfd,&msg,sizeof(Msg),0);
255     printf("%d\n",msg.acc.flag);
256     //根据判断结果跳转界面
257     if(0 == msg.acc.flag)
258     {
259         if(0 == msg.acc.sp)
260         {
261             loading();
262             ano_main(msg.acc.account);
263         }
264         else
265         {
266             printf("该账号已在其他客户端登录!\n");
267             sleep(2);
268             return;
269         }
270     }
271     else if(3 <= msg.acc.flag)
272     {
273         printf("账号已被锁定!请先前往解锁!\n");
274         sleep(2);
275         return;
276     }
277     else
278     {
279         printf("登录失败!用户或密码错误!\n");
280         sleep(2);
281         return;
282     }    
283 }
284 
285 //解锁界面
286 void unlock_menu(void)
287 {
288     Msg msg = {3};
289     printf("请输入要解锁的账号:");
290     scanf("%d",&msg.acc.account);
291     //清空缓冲区
292     stdin->_IO_read_ptr = stdin->_IO_read_end;
293     printf("请输入身份证号:");
294     gets(msg.acc.idcard);
295     printf("请输入新密码:");
296     put_pw(msg.acc.password);
297     //将获得的基本信息发送到服务端
298     send(sockfd,&msg,sizeof(Msg),0);
299     //接收服务端传回的信息(账号id)
300     recv(sockfd,&msg,sizeof(Msg),0);
301     if(-1 == msg.acc.flag)
302     {    
303         printf("输入信息不正确或该账户不需要解锁!\n");
304         sleep(2);
305         return;
306     }
307     printf("解锁成功!\n");
308     printf("*****您的id是%d,新密码为%s*****\n",msg.acc.account,msg.acc.password);
309     sleep(2);
310     return;    
311 }
312 
313 //销户界面
314 void delete_menu(void)
315 {
316     Msg msg = {4};
317     //获取账号密码
318     printf("请输入账号:");
319     scanf("%d",&msg.acc.account);
320     //清空缓冲区
321     stdin->_IO_read_ptr = stdin->_IO_read_end;
322     printf("请输入密码:");
323     put_pw(msg.acc.password);
324     //将获得的基本信息发送到服务端
325     send(sockfd,&msg,sizeof(Msg),0);
326     //接收服务端传回的信息(账号id)
327     recv(sockfd,&msg,sizeof(Msg),0);
328     if(-2 == msg.acc.flag)
329     {
330         printf("销户成功!\n");
331         sleep(2);
332     }
333     else
334     {
335         printf("销户失败!\n");
336         sleep(2);
337     }
338     return;
339 }
340 int main()
341 {
342     // 创建socket对象
343     sockfd = socket(AF_INET,SOCK_STREAM,0);
344     if(0 > sockfd)
345     {
346         perror("socket");
347         return -1;
348     }
349     // 准备通信地址
350     struct sockaddr_in addr = {};
351     addr.sin_family = AF_INET;
352     addr.sin_port = htons(1904);
353     addr.sin_addr.s_addr = inet_addr("192.168.1.110");
354     // 连接
355     if(0 > connect(sockfd,(struct sockaddr*)&addr,sizeof(addr)))
356     {
357         perror("connect");
358         return -1;
359     }
360     
361     while(1)
362     {
363         system("clear");
364         show_menu();
365         switch(getch())
366         {
367             case 49:open_menu();break;
368             case 50:login_menu();break;
369             //case 51:unlock_menu();break;
370             //case 52:delete_menu();break;
371             case 53:return 0;
372         }
373     }
374 }

使用的工具函数

 1 #include "customer.h"
 2 
 3 //创建消息队列
 4 int create_msg_queue(int keynum)
 5 {
 6     //获取ipc键值
 7     key_t key = ftok("~",keynum);
 8     //创建消息队列
 9     int msgid = msgget(key,IPC_CREAT|0644);
10     if(0 > msgid)
11     {
12         perror("msgget");
13         return -1;
14     }
15     
16     return msgid;
17 }
18 
19 //隐藏密码输入
20 char* put_pw(char* pw)
21 {
22     for(int i=0; i<20; i++)
23     {
24         stdin->_IO_read_ptr=stdin->_IO_read_end;
25         pw[i]=getch();
26         if(pw[i] == 127)
27         {
28             if(i>0)
29             {
30                 i -= 2;
31                 printf("\b \b");
32             }
33             else
34             {
35                 i--;
36             }
37         }
38         else if(pw[i] == 10)
39         {
40             pw[i]='\0';
41             break;
42         }
43         else
44         {
45             putchar('*');
46         }
47     }
48     return pw;
49 }

定义的头文件

 1 #ifndef CUSTOMER_H
 2 #define CUSTOMER_H
 3 
 4 #include <stdio.h>
 5 #include <sys/types.h>
 6 #include <sys/ipc.h>
 7 #include <sys/msg.h>
 8 #include <string.h>
 9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <fcntl.h>
12 #include <sys/wait.h>
13 #include <getch.h>
14 #include <stdbool.h>
15 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <pthread.h>
19 #include <semaphore.h>
20 #include <signal.h>
21 
22 #define key1 123456
23 #define key2 654321
24 typedef struct Account
25 {
26     int account;
27     int target;
28     char name[20];
29     char password[10];
30     char idcard[18];
31     float money;
32     int flag;
33     int sp;
34 }Account;
35 typedef struct Msg
36 {
37     long type;
38     Account acc;
39 }Msg;
40 
41 int create_msg_queue(int keynum);
42 char* put_pw(char* pw);
43 
44 #endif

Makefile

 1 all: 2 gcc -std=gnu99 -c customer.c 3 gcc -std=gnu99 -c tools.c 4 gcc customer.o tools.o -o customer -lpthread 

转载于:https://www.cnblogs.com/kid971220/p/10497801.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/484008.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么航空发动机那么难造?看看3D工作原理

来源&#xff1a;网络目前大部分航空发动机都是属于燃气涡轮型&#xff0c;民用客机的发动机突出的安全性和可靠性&#xff0c;而军用发动机在这个基础上还追求更大的推力&#xff0c;以及开加力时的最大推力。由此可见&#xff0c;航空发动机领域中最强者必然是军用航发&#…

OSGB格式解析

主要介绍倾斜摄影数据OSGB二进制数据的解析&#xff0c;首先简单介绍一下OpenSceneGraph相关技术&#xff0c;并介绍倾斜摄影数据的组织结构&#xff0c;着重分析OSGB格式的相关字段&#xff0c;最后逐字节对OSGB数据进行解析并通过OpenSceneGraph对数据进行可视化&#xff0c;…

《动手学深度学习》 第二天 (自动求梯度)

2.3、自动求梯度 MXNet提供的autograd模块可以用来自动求梯度。 2.3.1 一个简单的栗子 这里我们要求对函数 y 2xTx &#xff08;2乘以x的转秩乘以X&#xff09;求关于列向量 x 的梯度。(使用jupyter notebook) 1、 创建变量x,并赋初值 x nd.arange(4).reshape((4,1)) #…

Gartner发布2021年新兴技术成熟度曲线

来源&#xff1a;Gartner中国8月24日&#xff0c;Gartner 公司最新发布了“2021年新兴技术成熟度曲线”&#xff08;Hype Cycle for Emerging Technologies&#xff0c;2021&#xff09;。其中&#xff0c;建立信任&#xff0c;加速增长以及塑造变革将是三大主要趋势&#xff0…

Vue语法学习第一课——插值

学习关于Vue的插值语法 ① 文本值 &#xff1a; "Mustache"语法&#xff0c;即双大括号 1 <span>Message:{{msg}}</span> 注&#xff1a;双大括号中的msg值改变&#xff0c;插入的内容也会随之改变&#xff0c;可通过v-once指令限制&#xff0c;但会影响…

人工智能“上位”会让程序员消失吗?

大脑以及二进制代码&#xff08;图&#xff1a;Canva&#xff09;来源&#xff1a;Forbes作者&#xff1a;Nisha Talagala编译整理&#xff1a;科技行者写代码已经成了许多工作的一项关键技能。一些国家和学校甚至认为&#xff0c;编程语言是一种可以接受的外语。而在各种熙熙攘…

分类的IP地址

现有物理地址再有IP地址IP地址的表示方法为点分十进制法IP地址的设计思想&#xff1a;网络部分 主机部分 分类的IP地址 特征&#xff1a;根据不同特征的IP地址&#xff0c;事先约定好网络号所占的位数和主机号所占的位数。 A类地址 全球一共有27-2 个A类网络&#xff0c;每…

卫星对于物联网来说是一个非常好的选择

ALAMY来源&#xff1a;IEEE电气电子工程师对许多人来说&#xff0c;“物联网”一词可能会让人想起智能城市的努力&#xff0c;比如配备交通摄像头和空气质量传感器的路灯&#xff0c;或者在自己家里连接设备。一个很自然的问题是&#xff0c;为什么你从没想使用卫星连接任何这些…

利用子网掩码划分子网

分类IP地址的弊端 一个物理网络不能过大&#xff0c;否则网络性能很差&#xff0c;某个B类或A类IP网络无法全部用于单个物理网络分类IP地址分配不合理&#xff0c;利用率低分类IP地址设计的弊端 —— 不灵活&#xff0c;IP地址利用率不高 划分子网的思路 网络管理员将本应属于…

springcloud流程图

自己画的&#xff1a; 别人画的 别人画的2 转载于:https://www.cnblogs.com/dzhou/p/10504215.html

java 搭建 web服务器 socket实现

【写在前面】 云计算的第n个java作业&#xff0c;开始一直不懂为什么老师一直让我们写java web的小demo&#xff0c;不应该是hadoop啥的直接上框架嘛。后来慢慢了解到&#xff0c;其实java web 的一些内容确实是云计算的基础。这个demo是用java socket 来搭建一个web服务器&…

【趋势】未来十年计算机体系结构的历史和趋势

来源&#xff1a;机器之心先分享我对这篇文章的总结&#xff0c;或者我得到的启发&#xff1a;1、DSA&#xff08;Domain-Specific Architectures&#xff0c;特定领域的体系结构&#xff09;将成为未来十年甚至更长时间&#xff0c;计算机体系结构的趋势。登纳德缩放定律结束、…

java socket 实现增删改查 + 在线答题小案例

实现效果 &#xff08;1&#xff09; 在client端可以实现对数据库的操作&#xff08;Select&#xff0c;Insert&#xff0c;Update&#xff0c;Delete&#xff09; &#xff08;2&#xff09;数据库中创建一个考试表和学生表&#xff0c;考试表中问题是四项选择题&#xff08;…

90后斯坦福博士论文登Science封面!AI算法准确预测RNA三维结构

来源&#xff1a;Science编辑&#xff1a;yaxin、su「我们对大部分RNA的结构几乎一无所知。」半个世纪以来&#xff0c;确定生物分子的三维结构一直困惑着科学家&#xff0c;也是生物学的重大挑战之一。难就难在&#xff0c;RNA折叠成复杂三维结构的形状很难通过实验或计算来确…

Event Recommendation Engine Challenge分步解析第五步

一、请知晓 本文是基于&#xff1a; Event Recommendation Engine Challenge分步解析第一步 Event Recommendation Engine Challenge分步解析第二步 Event Recommendation Engine Challenge分步解析第三步 Event Recommendation Engine Challenge分步解析第四步 需要读者先阅读…

计算机网络之RIP协议与OSPF协议模拟、UDP与TCP编程,Wireshark抓包分析

通过Python模拟RIP协议,OSPF协议,并模拟UDP和TCP编程,并通过Wireshark抓包工具,对所发送的报文进行捕获分析。 文章目录 一、RIP协议的模拟与编程二、OSPF协议的模拟与编程三、UDP编程四、TCP套接字编程五、Wireshark 数据分析六、总结一、RIP协议的模拟与编程 1.1 题目 …

虚拟机 NAT模式与桥接模式的区别

同个人网站 https://www.serendipper-x.cn/&#xff0c;欢迎访问 &#xff01; NAT模式&#xff1a;相当于宿主机再构建一个局域网&#xff0c;虚拟机无法和本局域网中的其他真实主机进行通讯。只需要宿主机器能访问互联网&#xff0c;那么虚拟机就能上网&#xff0c;不需要再…

基础研究和前沿技术领域校企融合协同创新的国际经验及启示

来源&#xff1a;中国科学技术发展战略研究院作者&#xff1a;薛姝、何光喜、张文霞原载于《全球科技经济瞭望》2021年5月第5期摘要&#xff1a;促进大学与企业的合作是各个国家科技创新政策和创新体系建设的重点任务&#xff0c;近年来也出现了加强在基础研究和前沿技术领域加…

理解云计算三种服务模式——IaaS、PaaS和SaaS

云计算的服务模式仍在不断进化&#xff0c;但业界普遍接受将云计算按照服务的提供方式划分为三个大类&#xff1a;SaaS&#xff08;Software as a Service–软件即服务&#xff09; PaaS&#xff08;Platform as a Service–平台即服务&#xff09; IaaS&#xff08;Infrastruc…

术,路,心:陈天桥的大脑行旅

来源&#xff1a; 脑极体在互联网、云计算与电动汽车之后&#xff0c;连同资本、产业、学术界在内的社会各界&#xff0c;纷纷开始将目光投向更远的地方。下一个超级机会藏在何处&#xff1f;下一个改变人类文明的技术机遇何时触发&#xff1f;随着各国开始在国家战略层面布局下…