Hi ppl.
I´m sorry that this post is so big, but i´m really confused with the final
results of the work. This is a work for the faculty that must be delivered
ni 5 hours. The program is all done, but the admistrator dont send the
orders to the server, the other problem is that when the client terminates
the server also terminates, and it was suposed that the server continues
active until it gets the shutdown request.
Next i send the specifications of the work that is only a help to understand
the golds of this work.
The code of the program is in the second post "ATM program 2"
Specification of the work:
-The application to develop will be constituted by a client program who
makes the interface with the user and a server program that processes order
proceeding from the client. The server keeps a database of accounts of the
users. The information contained in the database, on each account, is the
following one: the name of the user and the sum of the balance. Some
customers can exist running simultaneously.
The client program must have the following functionality:
.. To ask for to the name and password to the user and to verify if this are
correct. For a question of implementation easiness, password is local and
only for all the common users. An user (administrator) with special
privileges have to exist, that will be indicated to follow; this user must
have one password different of password of the common users
.. In case that password is correct, it will have to present a menu, with the
operations that the user can effect, or else it will have to present an
error message
.. The menu to present to the common users for the client program will have
to include the following operations: to raise money, to deposit money, to
consult the balance and to leave
.. The menu of the administrator will have to include the following
operations: to create new account of client, to list the existing accounts,
to make shutdown of the costumer, to make shutdown of the server and to
leave
.. To send to the server, through a FIFO with name known of all the
customers, a message with the necessary information to the execution of the
service asked for the user
.. To wait for the reply of the server, envoy through a dedicated FIFO to the
client, and to present it the user.
The server program must have the following functionality:
.. To run in background and to accept the order of service and the command of
shutdown, from the clients
.. To be permanently to listening, in the FIFO with known name, of the order
sent by the clients
.. To launch one thread adequate to answer to each order of the customers
.. The reply to the customer thread. will have to be given by this
.. To refuse order of service that arrives after the shutdown command of the
server, sent by the client administrator, waiting, however, that reply is
given to the orders that they will be to be taken care of, before it ends.
Some details of implementation:
.. The relative information to the accounts of the users must be kept in an
Array, in core storage, during the execution of the serving process, being
kept in a permanent way in file (file of accounts), when shutdown of the
server will be made. The server must read the information contained in the
file of accounts to the Array, before initiating the attendance of the
clients
.. The internal Array of accounts will have to be always commanded and its
research made for binary research (to use qsort() and bsearch() of the
standard library of the C). It will have to grow when it will be case
.. The file of accounts is a text file, contends in the 1st line the number
of entries, followed of the entries, an entry in each one of the following
lines. Each entry is constituted by the name of client and the balance,
separate for "|", as it is illustrated following:
Example of content of accounts file:
3
Peter Norton|7500
Anna kournikova|1600000
Bono Vox|123456
The FIFO of reception of the orders of the clients, "request", must be
created by the server
.. Being "nnnnn" the PID of a client, the FIFO through which is sent the
answers to this client must have the name "ansnnnnn.". These FIFOS will have
to be created and destroyed per item of the clients. So that the server
program knows which the FIFO for where it must send messages/answers to the
clients, each order that a client sends to the server will have to contain a
field with the PID of the client
.. It is necessary to establish a protocol and format of messages to change
between clients and server. All the order of the clients must have a reply
of the server (for example, reply "OK", in the case of the order of creation
of a new account of client and shutdown).
.. Synchronization mechanisms must be foreseen between threads of the server
in order to prevent errors in the operations of creation of accounts,
survey, deposit and consultation of the balances
.. Shutdown of the server must be made in a synchronized way, guaranteeing
that the order that is to be taken care of is concluded. For this, it is
suggested the use of a flag, that will be activated when the server receive
the order of shutdown. After the flag have been activated the server will
not have to accept new orders, but it will have to wait that all threads,
that they are to take care of asked for, finish, before him self terminates.
General project of the server program:
.. to read the content of the file of accounts to the internal Array
.. to create FIFO of reception of orders of the clients (request)
.. while not to receive the command of shutdown
.. to read message, of the FIFO
.. if it received the command of shutdown, to activate flag of shutdown and o
finish this cycle
.. to remove of the message the PID of the client
.. to create thread to serve the order contained in the message, being passed
to it as argument the PID of the client
.. (the reply to the client it must be sent by thread, through pipe
"ansnnnnn")
.. to destroy pipe request
.. to wait that all threads finish
.. to write the content of the Array of accounts to the file of accounts
General project of the client program:
.. to wait that pipe of order reception (request) either created by the
server; if it will not be created to the end of 3 minutes, to write message
and to finish the program
.. to create pipe of reception of the answers to the order (ansnnnnn)
.. to send message to the server, with indication of the PID
.. to execute "an infinite" cycle (1)
.. to repeat the reading of password of user until he is correct
.. to repeat
.. to present the menu (different consonant the type of user)
.. to read the option of the user
.. if the option was "shutdown of the client", to finish the cycle (1)
.. if the option was "to leave", to come back to the beginning of the cycle
(1)
.. to send message to the server, in accordance with the option of the user,
through pipe "request";
(if pipe will have been destroyed, to finish the cycle (1))
.. to wait the reply, sent for the server through pipe "ansnnnnn"
.. to present the reply, formatted, in the screen
.. to destroy pipe "ansnnnnn".
- the possible situations will have to be dealt with all error, not to be
indicated in the previous projects.
Client program
**************************************************
**
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
#define MAXBUF 100
#define MENU_CLIENTE "menu_cliente.txt"
#define MENU_LEVANTAMENTOS "menu_levantamentos.txt"
void cliente(void);
void menu_cliente();
void menu_levantamentos();
void administrador(void);
void menu_administrador();
void username();
void password();
char name[MAXBUF];
char nome[MAXBUF];
int wf, flag = 0;
int main(void)
{
int n, espera = 0;
sprintf(name, "./ans%d", n = getpid());
mkfifo(name, 0600);
while(flag == 0)
{
do
{
if ((wf = open("./request", O_WRONLY)) == -1) //abre o FIFO do servidor com
permissão para escrever
{
sleep(1);
if(++espera > 6)
{
write(STDOUT_FILENO, "\n\n - De momento nao e possivel satisfazer os seus
pedidos - ", 62);
write(STDOUT_FILENO, "\n\n - Por favor dirija-se ao Mutibanco mais proximo -
", 62);
return 0;
}
}
}
while(wf == -1);
username();
password();
}
unlink(name);
return 0;
}
void username()
{
int i = 0;
char buf;
system("clear");
write(STDOUT_FILENO, "\n\n Introduza o seu username: ", 31);
do
{
read(STDIN_FILENO, &buf, 1);
nome[i] = buf;
i++;
}
while(buf != '\n');
nome[i-1] = '\0';
return;
}
void password()
{
int i, n = 0;
char pass[14], buf, ast = '*';
struct termios tms, tms_old;
do
{
write(STDOUT_FILENO, "\n\n Introduza a sua password: ", 30);
tcgetattr(STDIN_FILENO, &tms_old);
tms = tms_old;
tms.c_lflag &= ~(ECHO);
tms.c_lflag &= ~(ICANON);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &tms);
i=0;
buf = 'a';
while(buf != '\n') {
read(STDIN_FILENO, &buf, 1); //ler o caracter que se escreve
if(buf != '\n')
{
pass[i] = buf;
i++;
write(STDOUT_FILENO, &ast, 1);
}
}
pass[i] = '\0';
tcsetattr(STDIN_FILENO, TCSANOW, &tms_old);
if (strcmp(pass, "cliente") !=0 && strcmp(pass, "administrador") != 0)
{
if(n == 0)
{
system("clear");
printf("\n\n -Introduziu uma password incorrecta- \n");
printf("\n - Dispoe de mais duas tentativas - \n");
}
else
if(n == 1)
{
system("clear");
printf("\n\n -Introduziu uma password incorrecta- \n");
printf("\n - Dispoe de mais uma tentativa - \n");
}
else
if(n == 2)
{
system("clear");
printf("\n\n -Introduziu uma password incorrecta- \n");
printf("\n - O seu pedido nao sera atendido - \n");
sleep(4);
return;
}
n++;
}
}
while(strcmp(pass, "cliente") !=0 && strcmp(pass, "administrador") != 0);
if(!strcmp(pass, "cliente"))
cliente();
else
administrador();
return;
}
void cliente(void)
{
char pedido[MAXBUF], resposta[MAXBUF];
int operacao, montante;
int levantamento, rf, n;
int flagsair = 1;
while(flagsair)
{
system("clear");
menu_cliente();
scanf("%d", &operacao);
switch(operacao)
{
case 1:
sprintf(pedido, "%d|%d|%s|%d", getpid(), 1, nome, 0);
flagsair = 0;
break;
case 2:
system("clear");
menu_levantamentos();
scanf("%d", &levantamento);
switch(levantamento)
{
case 1:
montante = 20;
sprintf(pedido, "%d|%d|%s|%d", getpid(), 2, nome, montante);
flagsair = 0;
break;
case 2:
montante = 40;
sprintf(pedido, "%d|%d|%s|%d", getpid(), 2, nome, montante);
flagsair = 0;
break;
case 3:
montante = 50;
sprintf(pedido, "%d|%d|%s|%d", getpid(), 2, nome, montante);
flagsair = 0;
break;
case 4:
montante = 100;
sprintf(pedido, "%d|%d|%s|%d", getpid(), 2, nome, montante);
flagsair = 0;
break;
case 5:
montante = 200;
sprintf(pedido, "%d|%d|%s|%d", getpid(), 2, nome, montante);
flagsair = 0;
break;
case 6:
do
{
printf("\n\n Digite a importancia que deseja levantar: ");
scanf("%d", &montante);
sprintf(pedido, "%d|%d|%s|%d", getpid(), 2, nome, montante);
if(montante > 200)
{
system("clear");
printf("\n\n Nao sao permitidos levantamentos superiores a 200 euros ");
}
}
while(montante > 200);
flagsair = 0;
break;
}
break;
case 3: //depositar dinheiro
printf("\n\n Digite a importancia que deseja depositar: ");
scanf("%d", &montante);
sprintf(pedido, "%d|%d|%s|%d", getpid(), 3, nome, montante);
flagsair = 0;
break;
case 4: //sair do menu
flagsair = 0;
return;
break;
}
}
printf("\n\n O pedido foi: %s \n", pedido);
sleep(3);
if((write(wf, pedido, strlen(pedido)+1)) < 0)
{
close(wf);
printf("\n\n - Erro no acesso ao seu Banco - Por favor tente mais tarde -
\n");
}
else
{
close(wf);
rf = open(name, O_RDONLY);
while ((n = read(rf, resposta, MAXBUF)) > 0)
printf("\n\n %s \n", resposta);
sleep(4);
close(rf);
}
return;
}
void menu_cliente()
{
int fd, a;
int buf[1];
fd = open("menu_cliente.txt", O_RDONLY); //abre o ficheiro que descreve
while(a != 0)
{
a = read(fd, buf, 1);
printf("%c", buf[0]);
}
close(fd);
return;
}
void menu_levantamentos()
{
int fd, a;
char buf[3];
fd = open("menu_levantamentos.txt", O_RDONLY); //abre o ficheiro que
descreve
while(a != 0)
{
a = read(fd, buf, 1);
printf("%c", buf[0]);
}
close(fd);
return;
}
void administrador(void)
{
int flagsair = 1;
int operacao, montante;
char pedido[MAXBUF], resposta[MAXBUF];
int rf, n;
while(flagsair)
{
system("clear");
menu_administrador();
scanf("%d", &operacao);
switch(operacao)
{
case 1:
printf("\n\n Nome do cliente: ");
scanf("%s", nome);
printf("\n\n Saldo da conta: ");
scanf("%d", &montante);
sprintf(pedido, "%d|%d|%s|%d", getpid(), 4, nome, montante);
break;
case 2:
sprintf(pedido, "%d|%d|%s|%d", getpid(), 5, "", 0);
break;
case 3:
flagsair = 0;
flag = 1;
return;
case 4:
sprintf(pedido, "%d|%d|%s|%d", getpid(), 6, "", 0);
break;
case 5:
flagsair = 0;
return;
}
}
printf("\n O pedido foi:\n[ %s ]\n", pedido);
sleep(5);
if((write(wf, pedido, strlen(pedido)+1)) < 0)
{
close(wf);
printf("\n\n - A comunicação não foi estabelecida -\n");
}
else
{
close(wf);
rf = open(name, O_RDONLY);
while ((n = read(rf, resposta, MAXBUF)) > 0)
printf("\n A resposta foi: \n\n %s \n", resposta);
sleep(5);
close(rf);
}
return;
}
void menu_administrador()
{
int fd, a;
int buf[1];
fd = open("menu_administrador.txt", O_RDONLY);
while(a!=0)
{
a = read(fd, buf, 1);
printf("%c", buf[0]);
}
close(fd); return;
}
**************************************************
**
server program
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#define FIFO_NAME "request"
#define FILE_NAME "conta.txt"
#define MAXBUFO 100
#define MAXBUF 100
#define MAXBUFA 100
void *escreve(void *);
void le_ficheiro(void);
void cria_conta(char *, int);
int compara(const void*, const void*);
void le_saldo(char *);
void levanta_dinheiro(char *, int);
void deposita_dinheiro(char *, int);
void cria_conta(char *, int);
void listacontas(void);
void shutdown(void);
void escreve_ficheiro(void);
typedef struct ficha
{
char nome[50];
int saldo;
}contas;
contas *conta;
int num_contas, flag = 0;
char resposta[MAXBUFA];
int main(void)
{
FILE *fp;
char buf[MAXBUF];
char caracter;
int cont = 0;
char *temp;
pthread_t tid;
le_ficheiro();
qsort(conta, num_contas, sizeof(contas), compara);
mkfifo("./request", 0644);
fp = fopen(FIFO_NAME, "r");
//while(flag == 0);
//{
caracter = fgetc(fp);
while(caracter != EOF)
{
if(caracter == '\0')
{
buf[cont] = '\0';
cont++;
}
else
{
buf[cont] = caracter;
cont++;
}
caracter = fgetc(fp);
}
fclose(fp);
temp = (char *)malloc(cont);
strcpy(temp, buf);
pthread_create(&tid, NULL, escreve, (void *)temp);
//onde foi colocado o que estava o que veio do FIFO
pthread_join(tid, NULL);
//}
unlink("./request");
escreve_ficheiro();
return 0;
}
void le_ficheiro(void)
{
FILE *fp;
char caracter;
char name[100], saldos[100], n_contas[100];
int cont=0, conto=0, contu=0, n=0, i=0, salda;
fp = fopen(FILE_NAME, "r");
caracter = fgetc(fp);
while(caracter != EOF)
{
if(n == 0)
{
if(caracter == '\n')
{
n_contas[cont] = '\0';
cont = 0;
n++;
}
else
{
n_contas[cont] = caracter;
cont++;
}
caracter = fgetc(fp);
num_contas = atoi(n_contas);
conta = (contas*) malloc(sizeof(contas) * num_contas);
}
else
if(n == 1)
{
if(caracter == '|')
{
name[conto] = '\0'; //termina as strings que contêm os nomes
conto = 0;
n++;
strcpy(conta[i].nome, name); }
}
else
{
name[conto] = caracter;
conto++;
}
caracter = fgetc(fp);
}
else
if(n == 2)
{
if(caracter == '\n')
{
saldos[contu] = '\0';
contu = 0;
n--;
salda = atoi(saldos);
conta[i].saldo = salda;
i++;
}
else
{
saldos[contu] = caracter;
contu++;
}
caracter = fgetc(fp);
}
}
fclose(fp);
return;
}
int compara(const void *a, const void *b)
{
return strcasecmp(a, b);
}
void *escreve(void *arg)
{
char pide[MAXBUFO], operacao[MAXBUFA], cliente[MAXBUFA], montante[MAXBUFA],
name[20];
char caracter;
int wf, n = 1, opera, montant;
int cont = 0, conta = 0, conto = 0, contu = 0, contador = 0;
char *meu_buf;
meu_buf = (char *)arg;
printf("\n O que vem do cliente e: %s\n", meu_buf);
caracter = meu_buf[contador];
while(caracter != '\0')
{
if(n == 1)
{
if(caracter == '|') "|"
{
pide[conta] = '\0';
conta++;
n++;
}
else
{
pide[conta] = caracter;
conta++;
}
contador++;
caracter = meu_buf[contador];
}
if(n == 2)
{
if(caracter == '|') "|"
{
operacao[cont] = '\0';
cont++;
n++;
}
else
{
operacao[cont] = caracter;
cont++;
}
contador++;
caracter = meu_buf[contador];
}
if(n == 3)
{
if(caracter == '|') "|"
{
cliente[conto] = '\0';
printf("{%s}\n", cliente);
conto++;
n++;
}
else
{
cliente[conto] = caracter;
conto++;
}
contador++;
caracter = meu_buf[contador];
}
if(n == 4)
{
montante[contu] = caracter;
contu++;
contador++;
caracter = meu_buf[contador];
}
}
montante[contu] = '\0';
opera = atoi(operacao);
montant = atoi(montante);
switch(opera)
{
case 1:
le_saldo(cliente);
break;
case 2:
levanta_dinheiro(cliente, montant);
break;
case 3:
deposita_dinheiro(cliente, montant);
break;
case 4:
cria_conta(cliente, montant);
break;
case 5:
listacontas();
break;
case 6:
shutdown();
break;
}
sprintf(name, "./ans%s", pide);
wf=open(name, O_WRONLY);
write(wf, resposta, strlen(resposta)+1);
return 0;
}
void le_saldo(char *cliente)
{
int montante;
contas *user;
printf("\n\n [%s]\n\n", cliente);
user = bsearch(cliente, conta, num_contas, sizeof(contas), compara);
if(user != NULL)
{
montante = user->saldo;
printf("\n\n O saldo do %s e de %d euros \n\n", cliente, montante);
sprintf(resposta,"O saldo do %s e de %d euros", cliente, montante);
}
else
{
printf("\n\n Não existe a conta da qual pretende saber o saldo \n\n");
sprintf(resposta, "Não existe a conta da qual pretende saber o saldo");
}
return;
}
void levanta_dinheiro(char *cliente, int montant)
{
int saldo;
contas *user;
user = bsearch(cliente, conta, num_contas, sizeof(contas), compara);
if(user == NULL) {
printf("\n\n Não existe a conta da qual pretende levantar %d euros\n\n",
montant);
sprintf(resposta, "Não existe a conta da qual pretende levantar %d euros",
montant);
}
else
{
if((((contas *)user)->saldo) - montant < 0)
{
printf("\n\n O seu saldo nao lhe permite efectuar essa operacao\n\n");
sprintf(resposta, "O seu saldo nao lhe permite efectuar essa operacao");
}
else
{
saldo = (((contas *)user)->saldo) - montant;
(((contas *)user)->saldo) = saldo;
printf("\n\n Foi efectuado um levantamento de %d euros\n\n", montant);
sprintf(resposta, "Foi efectuado um levantamento de %d euros", montant);
}
}
return;
}
void deposita_dinheiro(char *cliente, int montant)
{
int saldo;
contas *user;
user = bsearch(cliente, conta, num_contas, sizeof(contas), compara);
if(user == NULL)
{
printf("\n\n Não existe a conta na qual pretende depositar %d euros\n\n",
montant);
sprintf(resposta, "Não existe a conta na qual pretende depositar %d euros",
montant);
}
else
{
saldo = (((contas *)user)->saldo) + montant;
(((contas *)user)->saldo) = saldo;
printf("\n\n Foi efectuado um deposito de %d euros\n\n", montant);
sprintf(resposta, "Foi efectuado um deposito de %d euros", montant);
}
return;
}
void cria_conta(char *cliente, int montant)
{
contas *user;
contas *temporario;
user = bsearch(cliente, conta, num_contas, sizeof(contas), compara);
if(user == NULL)
{
num_contas++;
temporario = (contas*) malloc(sizeof(contas) * num_contas);
memcpy(temporario, conta, sizeof(contas)*(num_contas - 1));
free(conta);
conta = temporario;
strcpy(conta[num_contas -1].nome, cliente);
conta[num_contas -1].saldo = montant;
}
return;
}
void listacontas(void)
{
int i = 0;
for (i = 0; i < num_contas ;i++ )
{
printf("\n | %s | %d |", conta[i].nome, conta[i].saldo);
sprintf(resposta, "| %s | %d |", conta[i].nome, conta[i].saldo);
}
return;
}
void escreve_ficheiro(void)
{
FILE *fw;
int i = 0;
fw = fopen(FILE_NAME, "w");
fprintf(fw, "%d\n", num_contas);
for(i = 0; i < num_contas; i++)
{
fprintf(fw, "%s|%d\n", conta[i].nome, conta[i].saldo);
}
return;
}
|