1、功能要求

包括两类用户:管理人员和普通用户(本文只写了普通用户程序)

普通用户功能:登录登出、存取款、转账、查询余额

2、技术要求

要求用到多进程多线程

要求同时允许多个用户操作(因为没有注册账号功能,且只初始化了两个账号信息,所以同时只能允许两个账号在线)

3、程序编写

第一次写C/S架构的程序,很多可能对于其他人来说很简单的问题我之前都没遇到过,所以写的过程中充满了艰辛,主要有几个问题让我困扰好久:

(1)客户端服务器之间的通信,整个socket框架借鉴的网上其他人的博客内容;

(2)技术要求中写道要用多进程多线程,一开始以为两个技术都要用到,纠结了老半天,网上查资料才明白选择一种应该就可以了,好像是因为两个技术同时使用容易出问题,具体也不太明白,我这里使用的多线程,需要注意的是在线程函数中传递参数的问题,具体可看程序或网上其他分析;

(3)socket编程客户端和服务器之间收发数据时,send和recv函数都是传送的一个数据缓冲区(const char FAR *buf),而银行系统中根据不同的操作,发送的数据类型和个数是不一样的,根据网上资料,本文将所有要发送或接受的数据定义在一个结构体中(分别是sendMsg和recvMsg),发送的时候可以直接发送结构体地址信息(sendMsg),且因为数据缓冲区(buf)传送的是字符串,最后一个字符为'\o',所以发送端的大小必须为(sizeof(sMsg)+1);在接收数据时,只能将接收到的数据存放在数据缓冲区(buf)中,然后再通过memcpy函数将其转换成对应的结构体(recvMsg),需要注意的是客户端和服务器中的结构体名称虽然可以不一样,但是两个结构体中对应的变量位置一定要相同,因为在发送和接收的时候,memcpy函数只把数据解析到对应位置。

服务器 server.c

#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>#define SERVER_PORT 8888 //端口号,定义为宏方便以后直接修改
#define BACKLOG     10   //表服务器可以同时监测多少个客户端连接,设置为>0即可struct accountMsg
{//char *name;int password;int account;int balance;//余额//bool uCal;//账户类型
};struct accountMsg accountMsg1[10];struct recvMsg
{//char *name;          //户主姓名int account;      //账号int password;       //密码int money;          //金额int uCal;           //账户类型int taskID;           //操作任务类型};//—————————————————————————登录验证—————————————————————————————
int login(int iSocketClient,struct recvMsg rMsg)
{int iSendLen;int iRecvLen;int accessBuf=0;printf("____________login ing__________\n");int uid;for(uid=0;uid<10;uid++){if(rMsg.account == accountMsg1[uid].account && rMsg.password == accountMsg1[uid].password ){accessBuf = 1;break;}}if (accessBuf !=1){printf("__________login failed__________\n\n");}iSendLen = send(iSocketClient, &accessBuf, sizeof(accessBuf), 0);if (iSendLen <= 0){printf("__________message zend error__________\n\n");close(iSocketClient);return -1;}if(accessBuf == 1){printf("__________client login succeed!__________\n\n");accessBuf=0;}return uid;
}//——————————————————————————存钱——————————————————————————
int saveMoney(int iSocketClient,struct recvMsg rMsg,int uid)
{printf("___________save Money ing__________\n");int iSendLen;accountMsg1[uid].balance = accountMsg1[uid].balance + rMsg.money;iSendLen = send(iSocketClient, &accountMsg1[uid].balance, sizeof(accountMsg1[uid].balance), 0);if (iSendLen <= 0){printf("___________save Money failed__________\n\n");close(iSocketClient);return -1;}printf("___________save Money succeed__________\n\n");return 0;
}//——————————————————————————取钱—————————————————————————————
int withdrawMoney(int iSocketClient,struct recvMsg rMsg,int uid)
{printf("___________withdraw Money ing__________\n");int iSendLen;int balance;balance = accountMsg1[uid].balance - rMsg.money;iSendLen = send(iSocketClient, &balance, sizeof(balance), 0);if (iSendLen <= 0){printf("___________withdraw Money failed__________\n\n");close(iSocketClient);return -1;}else if(balance >= 0){accountMsg1[uid].balance = balance;}printf("___________withdraw Money END__________\n\n");return 0;
}//——————————————————————————转账—————————————————————————————
int transferMoney(int iSocketClient,struct recvMsg rMsg,int uid)
{printf("___________transfer Money ing__________\n");int iSendLen;int balance;balance = accountMsg1[uid].balance - rMsg.money;int tuid;for(tuid=0;tuid<10;tuid++){//核对转账账号是否存在if(rMsg.account == accountMsg1[tuid].account && tuid != uid){ break;}}//账号不存在if(tuid>=10){printf("__________account do not exit_________\n\n");balance = -1;}iSendLen = send(iSocketClient, &balance, sizeof(balance), 0);if (iSendLen <= 0){printf("___________transfer Money failed__________\n\n");close(iSocketClient);return -1;}else if(balance >= 0 && tuid < 10)//send成功后再修改账户余额{accountMsg1[uid].balance = balance; //登录用户账号余额accountMsg1[tuid].balance = accountMsg1[tuid].balance + rMsg.money; //被转账用户账号余额}printf("___________transfer Money END__________\n\n");return 0;
}int balanceEnquire(int iSocketClient,struct recvMsg rMsg,int uid)
{   printf("___________balance Enquire ing__________\n");int iSendLen;iSendLen = send(iSocketClient, &accountMsg1[uid].balance, sizeof(accountMsg1[uid].balance), 0);if (iSendLen <= 0){printf("___________balance Enquire failed__________\n\n");close(iSocketClient);return -1;}printf("___________balance Enquire succeed__________\n\n");return 0;
}//———————————————————————创建套接字——————————————————————————
int creatSocket()
{int iSocketServer;iSocketServer = socket(AF_INET, SOCK_STREAM, 0);if (-1 == iSocketServer){printf("socket error!\n");return -1;}struct sockaddr_in tSocketServerAddr;//服务器地址结构tSocketServerAddr.sin_family = AF_INET;tSocketServerAddr.sin_port   = htons(SERVER_PORT); tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;memset(tSocketServerAddr.sin_zero, 0, 8);int iRet;iRet = bind(iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));if (-1 == iRet){printf("bind error!\n");return -1;}iRet = listen(iSocketServer, BACKLOG);if (-1 == iRet){printf("listen error!\n");return -1;}return iSocketServer;
}//——————————————————————线程处理函数——————————————————————————
void *handle_client(void *arg)
{   int iSocketClient = *(int*)arg;int uid;printf("_____________________at handle thread____________________\n");while (1){printf("____________________waiting client operation...____________________\n\n");struct recvMsg rMsg;memset(&rMsg,0,sizeof(rMsg));char buf[1024]={0};int iRecvLen = recv(iSocketClient, buf,1025, 0);memcpy(&rMsg,buf,sizeof(rMsg)); if (iRecvLen <= 0){printf("_________________error recv_______________\n");break;}buf[iRecvLen] = '\0';//printf("_____3 rMsg.account:  %d  rMsg.password:  %d  rMsg.taskID: %d___\n",rMsg.account,rMsg.password,rMsg.taskID); switch(rMsg.taskID){case 0: uid = login(iSocketClient,rMsg);break;case 1: saveMoney(iSocketClient,rMsg,uid);break;case 2: withdrawMoney(iSocketClient,rMsg,uid);break;case 3: transferMoney(iSocketClient,rMsg,uid); break;case 4: balanceEnquire(iSocketClient,rMsg,uid); break;default:break;                    }}//close(iSocketClient);
}int main()
{memset(accountMsg1, 0, sizeof(accountMsg1)*10);accountMsg1[0].account = 123;accountMsg1[0].password = 456;accountMsg1[0].balance = 800;//accountMsg1[0].uCal = 1;//普通用户accountMsg1[1].account = 1212;accountMsg1[1].password = 3456;accountMsg1[1].balance = 500;int iSocketServer;iSocketServer=creatSocket();if (-1 == iSocketServer){printf("create socket failed!\n");return -1;}struct sockaddr_in iSocketClientAddr;//客户端地址结构:当客户端来连接时会传过来int iAddrLen;int iRecvLen;printf("____server running,waiting for client conneting...__\n");while (1){iAddrLen = sizeof(struct sockaddr);int iSocketClient = accept(iSocketServer, (struct sockaddr *)&iSocketClientAddr, &iAddrLen);if (-1 != iSocketClient){printf("___accepted client message successed!__\n");pthread_t pid;pthread_create(&pid,NULL,handle_client,&iSocketClient);pthread_detach(pid);               }   //close(iSocketServer);}close(iSocketServer);return 0;
}

客户端 client.c

#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>#define SERVER_PORT 8888struct sendMsg
{//char *name;      //户主姓名int account;      //账号int password;       //密码int money;      //金额int uCal;       //账户类型int taskID;       //操作任务类型};int verify(int iSocketClient,struct sendMsg sMsg)     //验证密码
{printf("_________verify user info ing_______\n\n");int iSendLen;int iRecvLen;iSendLen = send(iSocketClient, (char *)&sMsg, sizeof(sMsg)+1, 0);//free(buf);if (iSendLen <= 0){close(iSocketClient);return -1;}//char accessBuf[20];int accessBuf=0;iRecvLen = recv(iSocketClient, &accessBuf, sizeof(accessBuf), 0);if (iRecvLen <= 0){   close(iSocketClient);return -1;}if(0 == accessBuf){return -1;}printf("_________verify user info succeed!_______\n\n");return 0;
}void login(int iSocketClient)
{struct sendMsg sMsg;   loop0:printf("\n_____Welcome to bank client!_____\n\n");memset(&sMsg,0,sizeof(sMsg));loop1:printf("Please choose your identity:\n");printf("0 Manager      1 User\n");scanf("%d",&sMsg.uCal);if(1 != sMsg.uCal){if(0 != sMsg.uCal){printf("identity error! \n");goto loop1;}}       loop2:printf("account: ");scanf("%d",&sMsg.account);printf("password: ");scanf("%d",&sMsg.password);if(0 != verify(iSocketClient,sMsg)){printf("account or password error,please relogin! \n");goto loop2;}while(1){printf("_____________Welcome to bank client!_____________\n");printf("_____________Main Business_____________\n\n");printf("1 saveMoney \n2 withdrawMoney \n3 transferMoney \n4 balanceEnquire \n5 exit\n");printf("\nPlease enter the business ID:");scanf("%d",&sMsg.taskID);printf("\n");switch(sMsg.taskID){case 1: saveMoney(iSocketClient,sMsg);break;case 2: withdrawMoney(iSocketClient,sMsg);break;case 3: transferMoney(iSocketClient,sMsg); break;case 4: balanceEnquire(iSocketClient,sMsg); break;case 5: goto loop0;break;default:break;           }}}int balanceEnquire(int iSocketClient,struct sendMsg sMsg)
{   int iSendLen;int iRecvLen;printf("___________balance Enquire ing__________\n\n"); iSendLen = send(iSocketClient, &sMsg, sizeof(sMsg), 0);if (iSendLen <= 0){close(iSocketClient);return -1;}int balanceBuf;iRecvLen = recv(iSocketClient, &balanceBuf, sizeof(balanceBuf), 0);if (iRecvLen <= 0){close(iSocketClient);return -1;}else{printf("Your balance is:  %d\n\n",balanceBuf );}return 0;
}int saveMoney(int iSocketClient,struct sendMsg sMsg)
{int iSendLen;int iRecvLen;printf("___________save Money ing__________\n\n"); printf("please enter the money: ");scanf("%d",&sMsg.money);iSendLen = send(iSocketClient, &sMsg, sizeof(sMsg), 0);if (iSendLen <= 0){close(iSocketClient);return -1;}int balanceBuf;iRecvLen = recv(iSocketClient, &balanceBuf, sizeof(balanceBuf), 0);if (iRecvLen <= 0){close(iSocketClient);return -1;}else{printf("Save Succeed!\n Your balance is:  %d\n\n",balanceBuf );}return 0;
}int withdrawMoney(int iSocketClient,struct sendMsg sMsg)
{int iSendLen;int iRecvLen;printf("___________withdraw Money ing__________\n\n"); printf("please enter the money: ");scanf("%d",&sMsg.money);iSendLen = send(iSocketClient, &sMsg, sizeof(sMsg), 0);if (iSendLen <= 0){close(iSocketClient);return -1;}int balanceBuf;iRecvLen = recv(iSocketClient, &balanceBuf, sizeof(balanceBuf), 0);if (iRecvLen <= 0){close(iSocketClient);return -1;}else if(balanceBuf < 0){printf("withdraw failed!\n Your balance is not sufficient!\n\n" );}else{printf("withdraw Succeed!\n Your balance is:  %d\n\n",balanceBuf );}return 0;}int transferMoney(int iSocketClient,struct sendMsg sMsg)
{printf("___________transfer Money ing__________\n\n");int iSendLen;int iRecvLen;printf("please enter payee's account: ");scanf("%d",&sMsg.account);printf("please enter the money: ");scanf("%d",&sMsg.money);iSendLen = send(iSocketClient, &sMsg, sizeof(sMsg), 0);if (iSendLen <= 0){close(iSocketClient);return -1;}int balanceBuf;iRecvLen = recv(iSocketClient, &balanceBuf, sizeof(balanceBuf), 0);if (iRecvLen <= 0){printf("___________transfer Money failed__________\n\n");close(iSocketClient);return -1;}else if(balanceBuf < 0){printf("transfer failed!\n The account is wrong or your balance is not sufficient! \n\n" );}else{printf("transfer Succeed!\n Your balance is:  %d\n\n",balanceBuf );}return 0;
}int CreatSocekt()
{int iSocketClient;iSocketClient = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in tSocketServerAddr;   tSocketServerAddr.sin_family = AF_INET;tSocketServerAddr.sin_port   = htons(SERVER_PORT);tSocketServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);   if (0 == inet_aton("10.1.65.142", &tSocketServerAddr.sin_addr)){printf("Server IP error!\n");return -1;}memset(tSocketServerAddr.sin_zero, 0, 8);int iRet;iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));  if (-1 == iRet){printf("connect failed!!\n");return -1;}return iSocketClient;
}int main()
{   int iSocketClient = CreatSocekt();if (-1 == iSocketClient){printf("socket error!\n");return -1;}login(iSocketClient);close(iSocketClient);return 0;
}

注:linux系统中,因为使用了多线程函数,所以编译时加上 -lpthread

gcc server.c -o server -lpthread

gcc client.c -o client -lpthread

银行业务系统(c/s架构、socket网络编程、多线程)相关推荐

  1. python socket mysql_5.Python操作MySQL,三层架构,Socket网络编程

    Python操作MySQL - MySQL之查询操作 - MySQL之插入数据 - MySQL之批量插入数据 - MySQL之删除数据 - MySQL之更新数据库 - MySQL之事务 - MySQL ...

  2. socket网络编程多线程

    #!/usr/bin/env python #-*-coding:utf-8-*- #多进程 import threading import time def thfun():s=0for i in ...

  3. Linux C++/Java/Web/OC Socket网络编程

    一,Linux C++ Socket网络编程 1.什么是TCP/IP.UDP? TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制 ...

  4. Socket网络编程(2)--服务端实现

    中秋了,首先祝大家中秋快乐,闲着无事在家整一个socket的聊天程序,有点仿QQ界面,就是瞎折腾,不知道最后是不是能将所有功能实现. 如果你对socket不了解,请看这篇文章:http://www.c ...

  5. Linux Kernel TCP/IP Stack — Socket Layer — TCP/UDP Socket 网络编程

    目录 文章目录 目录 TCP/UDP Socket 逻辑架构 创建 Socket 绑定 Socket 请求建立 Socket 连接 监听 Socket 接受请求 关闭连接 数据的发送和接收 send ...

  6. socket网络编程——套接字地址结构

    声明:此博客是本人根据老师课件总结的,如有抄袭行为,本人会即刻删除. 1.主机字节序列和网络字节序列 主机字节序列分为大端字节序和小端字节序,不同的主机采用的字节序列可能不同.大端字节序是指一个整数的 ...

  7. 【linux高级程序设计】(第十三章)Linux Socket网络编程基础 2

    BSD Socket网络编程API 创建socket对象 int socket (int __domain, int __type, int __protocol) :成功返回socket文件描述符, ...

  8. 多实例多进程网络编程PHP,php socket网络编程基础知识(四):多进程

    标签:status   传递   windows   返回   修改   队列   _for   响应   关联 说明 php在web编程时是不需要考虑多进程的,但整个php流程是涉及到多进程的,只不 ...

  9. Socket网络编程(TCP/IP/端口/类)和实例

    原文:C# Socket网络编程精华篇 转自:微冷的雨 我们在讲解Socket编程前,先看几个和Socket编程紧密相关的概念: TCP/IP层次模型 当然这里我们只讨论重要的四层 01,应用层(Ap ...

  10. Day09: socket网络编程-OSI七层协议,tcp/udp套接字,tcp粘包问题,socketserver

    今日内容:socket网络编程     1.OSI七层协议     2.基于tcp协议的套接字通信     3.模拟ssh远程执行命令     4.tcp的粘包问题及解决方案     5.基于udp协 ...

最新文章

  1. oracle批处理参数调用,bat调用jar包并传入多个参数
  2. flask中jinjia2模板引擎详解3
  3. MySQL索引(B+Tree 索引、哈希索引、全文索引、 空间数据索引)、索引优化、优点、使用场景
  4. 洛谷P3006 [USACO11JAN]瓶颈Bottleneck(堆模拟)
  5. hadoop实训报告总结及体会_管理工程学院举办电子商务实训表彰大会
  6. 程序员如何通过书籍学习编程?小心用错方法,不然可能事倍功半!
  7. Python玩转各种多媒体,视频、音频到图片
  8. JavaScript变量提升
  9. day17--JQuery
  10. vue导入静态js_vue引入静态js文件的方法
  11. Google编程规范中文文档,非常详细
  12. 计算机网络习题(参考)
  13. ffmpeg将amr文件转成mp3文件
  14. 奥的斯服务器状态显示,OTIS服务器(TT)查看故障及清除故障的方法
  15. 增强现实(AR)智能眼镜的关键技术:标定、跟踪与交互
  16. Python实现计算机的自动化控制!
  17. 玩转华为ENSP模拟器系列 | 配置OSPF多进程
  18. android 的Zygote 分析
  19. Matlab谐波搭建
  20. Python标准-模块版本号命名-PEP-396PEP-386

热门文章

  1. A component required a bean of type ‘com.yida.data.religion.common.dao.AddressInfoMapper‘ that could
  2. PPT文件不能编辑怎么办?
  3. win10 任务栏通知区图标不见了
  4. matlab程序中ode45,关于matlab中ode45的问题
  5. 计算机基本组成及功能
  6. 解决使用maven打jar包缺失依赖包问题
  7. [iOS Xib加载/封装] xib加载以后无法赋值Laber属性的值
  8. ABAP ONF4 事件 查找表
  9. 处理txt文件下载下来以后,排版格式不对的问题
  10. Java基础之网络编程