系统描述:
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