Linux平台模拟ATM机系统

系统描述:

1.服务器端存储有客户的账号,姓名,以及存款数额,该数据存放在info.txt文件里面;

2.客户端模拟系统,把要模拟存,储客户的系列操作全部数据放在info.txt文件里面。

3.模拟过程为:事先启动服务器端,然后再启动客户端,该过程开始模拟,要支持多点请求服务,以及程序的可靠,稳定,以及高效。

4.该模拟过程在Linux平台下面开发,采用Socket TCP/IP通信,服务器端采用Select I/O模型。

服务器端设计:

//server.h

/******************************************************
** this program is the server of the project.
**
** Date:11th March,2012
**
** Copyright@  Author: Tianmo   ID:M201176121.
**
*******************************************************/

#ifndef _SERVER_H_
#define _SERVER_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include "dataProcess.h"

#define PORT     88960    // the port users will be connecting to
#define BACKLOG  1024     // how many pending connections queue will hold
#define BUF_SIZE 1024
#define MAXLEN   32

int fd_A[ BACKLOG ];    // accepted connection fd

//the struct of the data
typedef struct node
{
	int AccountTime;		
	char AccountNum[ MAXLEN ];	
	char TransactionType;	
	int balanceAmount;
	
}PNode;

//The declaration of the function
void fun();
void sig_int(int );
void showclient(int conn_amount);
int sock_listen(int tcp_port);
void run();
#endif
/******************************************************
** this program is the server of the project.
**
** Date:11th March,2012
**
** Copyright@  Author: Tianmo   ID:M201176121.
**
*******************************************************/
#include "server.h"

int main(void)
{

	//set the signal
	struct sigaction action;
    action.sa_handler = (void*)fun;
    sigemptyset(&action.sa_mask);
    action.sa_flags = 0;
    sigaction(SIGPIPE,&action,NULL);
	
	//do the process about the data
	run();	
	signal(SIGINT, sig_int);	
	while(1)
    {   
		//everything done
        pause();    
    }		
	return 1;
}

void fun()
{
	printf("pipe is Closed.\n");
}

void sig_int(int signo)
{    
    exit(1);
}

void showclient(int conn_amount)
{
    int i;	
    printf("client amount: %d\n", conn_amount);   	
	/*
	for (i = 0; i < BACKLOG; i++) {
        printf("[%d]:%d  ", i, fd_A[i]);
	}
	*/
    printf("\n");
}
int sock_listen(int tcp_port)
{
	int sockfd;
	const int yes = 1;
	
	// server address information
	struct sockaddr_in server_addr;    
	
	if (-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0)))
	{
        perror("socket");
        exit(1);
    }	
    if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))) 
	{
        perror("setsockopt");
        exit(1);
    }    
	// host byte order
    server_addr.sin_family = AF_INET;
	
	// short, network byte order	
    server_addr.sin_port = htons(tcp_port);  

	// automatically fill with my IP	
    server_addr.sin_addr.s_addr = INADDR_ANY;

	//initial
    memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));	
	
    if (-1 == bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)))
	{
        perror("bind");
        exit(1);
    }	
    if (-1 == listen(sockfd,BACKLOG))
	{
        perror("listen");
        exit(1);
    }
	
	return sockfd;
}
void run()
{
	// listen on sock_fd, new connection on new_fd
    int i,ret,sock_fd, new_fd;  
	
	//the max sock connection and the total connection 
	int maxsock,conn_amount = 0;
	
	//the buf of receive
	char recv_buf[ BUF_SIZE ] = {0};//receive the data from the client
	char send_buf[ BUF_SIZE ] = {0};//send the data to client	
   
	//connector's address information
    struct sockaddr_in client_addr; 
    socklen_t sin_size = sizeof(client_addr);
	 
    fd_set fdsr;   
    struct timeval tv;
 
	//get the listen socket fd
 	printf("listen port %d\n", PORT);	
	sock_fd = sock_listen(PORT);	
	
	//get max socket fd
    maxsock = sock_fd;
	
	struct node  *p    = NULL;
	struct guest *head = NULL;
	
    while (1) {
	
        // initialize file descriptor set
        FD_ZERO(&fdsr);
        FD_SET(sock_fd, &fdsr);
		
        // timeout setting
        tv.tv_sec = 30;
        tv.tv_usec = 0;
		
        // add active connection to fd set
        for (i = 0; i < BACKLOG; i ++) 
		{
            if (0 != fd_A[i]) 
			{
                FD_SET(fd_A[i], &fdsr);
            }
        }
	
		//select
        ret = select(maxsock + 1, &fdsr, NULL, NULL, &tv);
        if (ret < 0) 
		{
            perror("select");
            break;
        } 
		else if (ret == 0) 
		{
            printf("timeout\n");
            continue;
        }
		
        // check every fd in the set
        for (i = 0; i < conn_amount; i ++) 
		{
            if (FD_ISSET(fd_A[i], &fdsr)) 
			{
				//receive the data from the client
                ret = recv(fd_A[i], recv_buf, sizeof(recv_buf), 0);				
				
				//judge this receive is successful or not
                if (ret <= 0) 
				{        
					//fail, client close
                    printf("client[%d] close\n", i);
					
                    close(fd_A[i]);
					
                    FD_CLR(fd_A[i], &fdsr);
					
					//the number of socket connection minues 1
					conn_amount --;
					
					//set 0
                    fd_A[i] = 0;
                }
				else 
				{        
					// receive data successfully
                    if (ret < BUF_SIZE)
					{
                        memset(&recv_buf[ ret ], '\0', 1);
					}
						
                    printf("client[%d] send:\n", i);
					
					
					p = (struct node *)malloc(sizeof(struct node));
					
					//from (char *) to (struct node *)
					p = (struct node *)recv_buf;
					
					//display the information from client
					printf("data received from source c\n");
					
					//display the data				
					printf("AccountTime      =  %d\n",p->AccountTime);
					printf("AccountNum       =  %s\n",p->AccountNum);
					printf("TransactionType  =  %c\n",p->TransactionType);
					printf("balanceAmount    =  %d\n",p->balanceAmount);					
					
					//begin process the request
					//get the informatino from the txt document
					//and put in the link list
					head = readfile();
					
					//display the data which in the txt document
					Display(head);
					
					//process the data,this is very important.
					Modify(head,p->AccountNum,p->TransactionType,p->balanceAmount,send_buf);
					
					//display the data which in the txt document again.
					Display(head);
					
					//save the data to the document.
					Save(head);
							
					//back the information to the client about this process 
					send(fd_A[i],send_buf,strlen(send_buf) + 1,0);
	
					//test this process
					//char str[] = "Good,very nice!\n";					
					//send(fd_A[i],str,sizeof(str), 0);				
                }
            }
        }
		
        // check whether a new connection comes
        if (FD_ISSET(sock_fd, &fdsr)) 
		{
            new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
			
            if (new_fd <= 0) 
			{
                perror("accept");
                continue;
            }
			
            // add to fd queue
            if (conn_amount < BACKLOG) 
			{
                fd_A[conn_amount ++] = new_fd;
				
                printf("new connection client[%d] %s:%d\n", conn_amount,
                       inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
					   
                if (new_fd > maxsock)
				{
                    maxsock = new_fd;
				}
            }
            else 
			{
				//if It is the max,we must be process.
                printf("max connections arrive, exit\n");
				
				//tell the message to client.
                send(new_fd, "bye", 4, 0);	
				
                close(new_fd);
				
                continue;
            }
        }
		
		//display the current amount of the connect socket.
        showclient(conn_amount);
    }
	
    // close other connections
    for (i = 0; i < BACKLOG; i++)
	{
        if (0 != fd_A[i])
		{
            close(fd_A[i]);
        }
    }
}
//dataProcess.h
/******************************************************
** this program is the server of the project.
**
** Date:11th March,2012
**
** Copyright@  Author: Tianmo   ID:M201176121.
**
*******************************************************/
#ifndef _DATAPROCESS_H_
#define _DATAPROCESS_H_

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>

#define MAXLEN 32

struct guestData
{
	//account number,account name, balance amount
	char accountNum[ MAXLEN ];

	char name[ MAXLEN ];

	int balanceAmount;
}GData;

struct guest
{
	struct guestData  data;

	struct guest *next;
}PGuest;

struct guest* Locate(struct guest *head,const char findmess[],const char nameornum[]) ;

void  Save(struct guest *head);

void  Display(struct guest *head);

void  Modify(struct guest *head,const char findmess[],const char choice,const int balaceAomunt,char *recvMessage);

struct guest* readfile();

void printstart();

void printc();

void printe(struct guest *p);

#endif
//dataProcess.c
/******************************************************
** this program is the server of the project.
**
** Date:11th March,2012.
**
** Copyright@  Author: Tianmo   ID:M201176121.
**
*******************************************************/

#include "dataProcess.h"
struct guest* Locate(struct guest *head,const char findmess[],const char nameornum[])  
{ 
	struct guest *r = NULL; 

	if(0 == strcmp(nameornum,"num")) 
	{ 
		r = head->next; 

		while(NULL != r) 
		{ 
			 if(0 == strcmp(r->data.accountNum,findmess)) 
			 {
				return r;
			 }

			 r = r->next; 
		} 
	} 
	else if(0 == strcmp(nameornum,"name")) 
	{ 
		 r = head->next; 

		 while(r != NULL) 
		 { 			 
			if(0 == strcmp(r->data.name,findmess))
			{	
				return r; 
			}
			
			 r = r->next; 
		 } 
	} 
	else
	{		
	}
	return NULL; 
}
void  Modify(struct guest *head,const char findmess[],const char choice,const int balaceAomunt,char *recvMessage)
{ 
	struct guest *p = NULL; 

	if(NULL == head->next) 
	{ 
		strcpy(recvMessage,"Tip: No information can be Modified!\n");
		
		printf("\nTip: No information can be Modified!\n"); 
	} 
	
	p = Locate(head,findmess,"num"); 

	if(NULL != p) 
	{ 
		if('d' == choice)
		{
			p->data.balanceAmount += balaceAomunt;
			
			strcpy(recvMessage,"Tip: Operation successful!\n");
			
			printf("Tip: Operation successful!\n");
		}			
		else if('w' == choice)
		{
			if(p->data.balanceAmount < balaceAomunt)
			{
				strcpy(recvMessage,"Tip:Balance is running low, the operation failed!\n");
				
				printf("Tip:Balance is running low, the operation failed!\n");
			}
			else
			{
				p->data.balanceAmount -= balaceAomunt;
				
				strcpy(recvMessage,"Tip: operation successful!\n");
				
				printf("Tip: operation successful!\n");
			}			
		}
		else
		{			
		}
	} 
	else 
	{
		strcpy(recvMessage,"=====>Tip: Do not find the appropriate account Number!\n");
				
		printf("\n=====>Tip: Do not find the appropriate account Number!\n");
	}
}
void Save(struct guest *head)
{ 
	FILE* fp; 

	struct guest *p = NULL; 

	int count = 0;            

	if((fp = fopen("info.txt","w")) == NULL) 
	{ 
		printf("\n=====>Tip: The error occurred while re-open the file!\n"); 

		exit(1); 
	}
	 
	p = head->next; 

	while(NULL != p ) 
	{ 
		fprintf(fp,"%-10s %-10s %-10d\n",p->data.accountNum,p->data.name,p->data.balanceAmount); 
		
		p = p->next;

		count ++;	 
	} 	
	
	printf("\nTip: Save the file successfully(%d records have been saved).\n",count); 
	
	fclose(fp); 
}

void  Display(struct guest *head) 
{ 
	int count = 0; 

	struct guest *p = NULL; 

	p = head->next; 

	if(NULL == p) 
	{ 
		printf("\n=====>Tip: No information can be displayed!\n"); 

	} 
	 printf("\t\n"); 

	 printstart(); 

	 printc(); 

	 printf("\n"); 

	 while(NULL != p) 
	 { 
		printe(p); 

		p = p->next; 
	 } 
	printstart(); 

	printf("\n"); 
}
struct guest* readfile()
{
	struct guest *head = NULL,*p1 = NULL,*p2 = NULL;

	FILE  *fp;

	int count = 0;

    p1 = (struct guest *)malloc(sizeof(struct guest));

	head = p1;

	if(NULL == (fp = fopen("info.txt","r")))
	{
		printf("Do not open the file.\n");
		
		exit(1);		
	}	
	
	while( !feof(fp) )
	{
	    p2 = (struct guest *)malloc(sizeof(struct guest));	     
		
		fscanf(fp,"%s%s%d\n",p2->data.accountNum,p2->data.name,&p2->data.balanceAmount);
		
		p2->next = NULL;

		p1->next = p2;

		p1 = p2;

		count ++;  
	}
	
	fclose(fp);	
	
	return head;
}
void printstart()
{
	printf("------------------------------------------------------------------------------\n");
}
void printc()
{
	printf("AccountNumber   AccountName    AccountBalance \n");
}
void printe(struct guest *p)
{
	printf("%-10s\t%-10s\t%-8d\t\n",p->data.accountNum,p->data.name,p->data.balanceAmount);
}
//info.txt
101 Wang  16000
102 John  1200
103 Gambo 11000
//Makefile
#server:server.o dataProcess.o
#	gcc -o -lpthread server server.o dataProcess.o
#server.o:server.c dataProcess.h
#	gcc -c -lpthread server.c
#dataProcess.o:dataProcess.c dataProcess.h
#	gcc -c dataProcess.c
#clean:
#	rm -f *.o server
#
CC = gcc
#CFLAGS = -lreadline -lhistory -lcurses -L/usr/lib/mysql/ -lmysqlclient -lz
CFLAGS = -lpthread
gg = server.o dataProcess.o
server: $(gg)
	$(CC) -o $@ $^ $(CFLAGS)
.c.o:
	$(CC) -c $<
clean:
	rm -rf *.o server
//client.c
/******************************************************
** this program is the client of the project.
**
** Date:11th March,2012.
**
** Copyright@  Author: Tianmo   ID:M201176121.
**
*******************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>  //socket
#include <sys/socket.h>
#include <netinet/in.h> //the struct of sockaddr_in

#define PORT       88960
#define SERVER_IP  "127.0.0.1"

#define MAXLEN     32
#define MAXBUF     1024

//the data which want to be processed
struct guestData
{
	int AccountTime;
	
	char AccountNum[ MAXLEN ];
	
	char TransactionType;
	
	int balanceAmount;		
};

struct node
{
	struct guestData  data;

	struct node *next;
};

//The declaration of the function
struct node* readfile();

void Display(struct node *head);

void processData(struct node *head);


int main()
{
	struct node *head = NULL;
	
	head = readfile();
	
	Display(head);	

	processData(head);
	
	return 0;
}

/**************************
**
** The function is: 
** Get the data from the document and put in a link list.
**
** Put in: None
**
** Return: the head of the link list
**
**************************/
struct node* readfile()
{
	FILE  *fp;

	int count = 0;

	struct node *head = NULL,*p1 = NULL,*p2 = NULL;
	
    p1 = (struct node *)malloc(sizeof(struct node));

	head = p1;

	if(NULL == (fp = fopen("info.txt","r")))
	{
		printf("Donnot open the file!\n");
		exit(1);
		
	}		
	while( !feof(fp) )
	{
	    p2 = (struct node *)malloc(sizeof(struct node));	     
		
		fscanf(fp,"%c%d%d%s\n",&p2->data.TransactionType,&p2->data.AccountTime,&p2->data.balanceAmount,p2->data.AccountNum);
				
		p2->next = NULL;

		p1->next = p2;

		p1 = p2;

		count ++;  
	}	
	fclose(fp);	
	
	return head;
}

/**************************
**
** The function is: 
** Display the data where already was in a link list.
**
** Put in: the head of the link list
**
** Return: None
**
**************************/
void Display(struct node *head) 
{
	struct node *p = NULL; 

	p = head->next; 

	if(NULL == p) 
	{ 
		printf("\n===>Tip: No information can be displayed!\n"); 
	} 
	
	printf(" AccountTime    TransactionType     AccountNum       balanceAmount\n");
	
	p = p->next;
	
	while(NULL != p) 
	{ 
		printf("%4d%4c%4s%4d\n",p->data.AccountTime,p->data.TransactionType,p->data.AccountNum,p->data.balanceAmount);
				
		p = p->next; 
	} 
	
	printf("\n"); 
}

/**************************
**
** The function is: 
** Send the data in a link list and display the information from the server.
**
** Put in: the head of the link list
**
** Return: None
**
**************************/
void processData(struct node *head)
{	
	int rec_len,sockfd;
	
	struct sockaddr_in server_addr;
	
	char *send_buf = NULL,receive_buf[ MAXBUF ];	
	
	//initial the receive_buf
	memset(receive_buf,0,sizeof(receive_buf));
	
	//Create socket
	if(-1 == (sockfd = socket(AF_INET,SOCK_STREAM,0)))
	{
		perror("socket");
        exit(1);
	}
	
	//get the size of server_addr
	socklen_t sizeaddr = sizeof(server_addr);
	
	//initial server_addr
	bzero(&server_addr,sizeof(server_addr));
	
	//set the propertial of server_addr
	server_addr.sin_family = AF_INET;
	server_addr.sin_port   = htons(PORT);
	server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

	//connect server
	if(-1 == connect(sockfd,(struct sockaddr*)&server_addr, sizeof(server_addr)))
	{
		perror("connect");
		exit(1);
	}
	
	//It is ready for send the data
	struct guestData *pData = NULL;
	struct node *p = head->next;
	
	//the first data will be sent
	p = p->next;

	while(NULL != p)
	{		
		//get the data
		pData = (struct guestData*)malloc(sizeof(struct guestData));		
		pData->AccountTime = p->data.AccountTime;				
		strcpy(pData->AccountNum,p->data.AccountNum);
		pData->TransactionType = p->data.TransactionType;		
		pData->balanceAmount = p->data.balanceAmount;
		
		//display the information which will be sent
		printf("AccountTime      =  %d\n",pData->AccountTime);
		printf("AccountNum       =  %s\n",pData->AccountNum);
		printf("TransactionType  =  %c\n",pData->TransactionType);
		printf("balanceAmount    =  %d\n",pData->balanceAmount);		
		
		//Cast the type of data from (struct guestData *) to (char *)	
		send_buf = (char *)pData;
		
		//wait for
		sleep(pData->AccountTime);
		
		//send
		if(-1 == send(sockfd,send_buf,MAXBUF,0))
		{
			perror("send");
			continue;
		}		
		
		//receive from the server information
		rec_len = recv(sockfd,receive_buf,sizeof(receive_buf),0);

		if(rec_len < 0)
		{
			perror("recv");
			exit(1);
		}
		else if(0 == rec_len)
		{
			continue;
		}
		else
		{
			if(rec_len < MAXBUF)
			{
				memset(&receive_buf[ rec_len ],'\0',1);
				
				//display the information from server
				printf("data received from source s\n");
					
				//print the data from the server
				printf("Server send: %s\n",receive_buf);
				
				//set the revceive_bur zero				
				memset(receive_buf,0,sizeof(receive_buf));
			}
		}
		
		//Start to procee the next data
		p = p->next;
	}	
	
	//At last,close the socket
	close(sockfd);
} 
//info.txt
w  10   200 101
d  25   300 101
d  26   150 105
//Makefile
client:client.o
	gcc -o client client.c
clean:
	rm -rf *.o client


你可能感兴趣的:(server,socket,struct,null,FP,Descriptor)