网络版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