Ajouts de la version non sécurisée + Makefile + Générateur de fichiers .db
This commit is contained in:
parent
675eaface8
commit
abd096bb21
Data
DataGenerator
Secured
Unsecured
512
Data/accounts.db
Normal file
512
Data/accounts.db
Normal file
File diff suppressed because it is too large
Load Diff
13
DataGenerator/Makefile
Normal file
13
DataGenerator/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
# Nom de l'exécutable
|
||||
TARGET = generate_accounts
|
||||
|
||||
# Fichier source
|
||||
SRC = generate_accounts.c
|
||||
|
||||
# Règle par défaut : compilation et lien
|
||||
all:
|
||||
gcc $(SRC) -o $(TARGET)
|
||||
|
||||
# Nettoyage des fichiers générés
|
||||
clean:
|
||||
rm -f $(TARGET)
|
71
DataGenerator/README.md
Normal file
71
DataGenerator/README.md
Normal file
@ -0,0 +1,71 @@
|
||||
# 🏦 Générateur de comptes bancaires
|
||||
|
||||
Ce programme en C permet de générer un fichier contenant des comptes bancaires aléatoires avec des noms et des montants répartis en fonction de vos paramètres. 🎲💰
|
||||
|
||||
## 🚀 Fonctionnalités
|
||||
- Génération de comptes avec des **prénoms réalistes** (ex. Emma, Moncef, Lenny).
|
||||
- Répartition personnalisée des montants par compte :
|
||||
- Total à distribuer.
|
||||
- Nombre de comptes.
|
||||
- Montants minimum et maximum par compte.
|
||||
- Exportation des données dans un fichier `.db` avec format fixe.
|
||||
|
||||
## 🛠️ Compilation
|
||||
Pour compiler le programme, utilisez la commande suivante dans votre terminal :
|
||||
|
||||
```bash
|
||||
gcc -o generate_accounts generate_accounts.c
|
||||
```
|
||||
|
||||
ou
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
## 🏃 Utilisation
|
||||
|
||||
### Commande
|
||||
```bash
|
||||
./generate_accounts -t <total_amount> -n <num_accounts> -m <min_amount> -M <max_amount> [-f <filename>]
|
||||
```
|
||||
|
||||
|
||||
| Option | Description | Obligatoire | Exemple |
|
||||
| ------ | --------------------------------------------------- | ----------- | ------- |
|
||||
| `-t` | Montant total à répartir entre les comptes | ✅ | `-t 10000` |
|
||||
| `-n` | Nombre total de comptes à générer | ✅ | `-n 5` |
|
||||
| `-m` | Montant minimum par compte | ✅ | `-m 500` |
|
||||
| `-M` | Montant maximum par compte | ✅ | `-M 3000` |
|
||||
| `-f` | Nom du fichier de sortie (par défaut `accounts.db`) | ❌ | `-f accounts.db` |
|
||||
|
||||
### Exemple
|
||||
#### Commande
|
||||
```bash
|
||||
./generate_accounts -t 10000 -n 5 -m 500 -M 3000 -f accounts.db
|
||||
```
|
||||
|
||||
#### Résultat attendu
|
||||
Fichier `accounts.db` :
|
||||
```yaml
|
||||
Emma 2500
|
||||
Liam 3000
|
||||
Olivia 1500
|
||||
Noah 2000
|
||||
Ava 1000
|
||||
```
|
||||
|
||||
|
||||
## ⚠️ Gestion des erreurs
|
||||
|
||||
1. Montant insuffisant pour répartir les comptes :
|
||||
```bash
|
||||
./generate_accounts -t 1000 -n 5 -m 500 -M 3000
|
||||
```
|
||||
**Erreur :** Paramètres invalides
|
||||
|
||||
2. Montant maximum inférieur au minimum :
|
||||
```bash
|
||||
./generate_accounts -t 10000 -n 5 -m 1000 -M 500
|
||||
```
|
||||
**Erreur :** Paramètres invalides
|
124
DataGenerator/generate_accounts.c
Normal file
124
DataGenerator/generate_accounts.c
Normal file
@ -0,0 +1,124 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define NAME_LENGTH 10 // Longueur fixe pour le nom
|
||||
#define ENTRY_LENGTH 16 // Longueur fixe pour une entrée (nom + argent + saut de ligne)
|
||||
|
||||
// Génère un nom aléatoire parmis une liste prédéfinie
|
||||
void generate_random_name(char *name) {
|
||||
const char *names[] = {
|
||||
"Emma", "Liam", "Olivia", "Noah", "Ava", "Oliver",
|
||||
"Sophia", "Elijah", "Isabella", "James", "Mia",
|
||||
"Charlotte", "Amelia", "Harper", "Evelyn", "Jack",
|
||||
"Benjamin", "Lucas", "Henry", "Alexander", "Ella",
|
||||
"Grace", "Chloe", "Lily", "Ellie", "Hannah", "Aiden",
|
||||
"Samuel", "Levi", "Owen", "Julian", "Nora", "Hazel",
|
||||
"Victoria", "Aurora", "Camila", "Aria", "Luna", "Scarlett",
|
||||
"Moncef", "Mohamed", "Ali", "Ahmed", "Hassan", "Hosni",
|
||||
"Lenny", "Khalid", "Louay", "Yanis", "Denis", "Luc",
|
||||
};
|
||||
int num_names = sizeof(names) / sizeof(names[0]);
|
||||
int index = rand() % num_names;
|
||||
|
||||
strncpy(name, names[index], NAME_LENGTH);
|
||||
name[NAME_LENGTH] = '\0'; // Assure que le nom est bien terminé
|
||||
}
|
||||
|
||||
// Génère un fichier de comptes aléatoires
|
||||
void generate_accounts(const char *filename, int total_amount, int num_accounts, int min_amount, int max_amount) {
|
||||
if (num_accounts <= 0 || min_amount < 0 || max_amount < min_amount || total_amount < num_accounts * min_amount) {
|
||||
fprintf(stderr, "Paramètres invalides.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *file = fopen(filename, "w");
|
||||
if (!file) {
|
||||
perror("Erreur à l'ouverture du fichier");
|
||||
return;
|
||||
}
|
||||
|
||||
srand(time(NULL));
|
||||
int remaining_amount = total_amount;
|
||||
|
||||
for (int i = 0; i < num_accounts; i++) {
|
||||
char name[NAME_LENGTH + 1];
|
||||
generate_random_name(name);
|
||||
|
||||
int max_for_account = remaining_amount - (num_accounts - i - 1) * min_amount;
|
||||
if (max_for_account > max_amount) {
|
||||
max_for_account = max_amount;
|
||||
}
|
||||
|
||||
int amount = (i == num_accounts - 1) ? remaining_amount : (rand() % (max_for_account - min_amount + 1) + min_amount);
|
||||
|
||||
remaining_amount -= amount;
|
||||
|
||||
// Formatage des données dans une ligne de 16 caractères
|
||||
char entry[ENTRY_LENGTH + 1];
|
||||
snprintf(entry, ENTRY_LENGTH + 1, "%-10s%5d\n", name, amount);
|
||||
|
||||
fwrite(entry, 1, ENTRY_LENGTH, file);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
printf("Comptes générés et enregistrés dans %s\n", filename);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Paramètres par défaut
|
||||
int total_amount = 0;
|
||||
int num_accounts = 0;
|
||||
int min_amount = 0;
|
||||
int max_amount = 0;
|
||||
char *filename = "accounts.db";
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "t:n:m:M:f:")) != -1) {
|
||||
switch (opt) {
|
||||
case 't':
|
||||
total_amount = atoi(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
num_accounts = atoi(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
min_amount = atoi(optarg);
|
||||
break;
|
||||
case 'M':
|
||||
max_amount = atoi(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
if (strlen(optarg) > 0) {
|
||||
filename = optarg;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Usage: %s -t total_amount -n num_accounts -m min_amount -M max_amount [-f filename]\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// Vérification des paramètres
|
||||
if (total_amount <= 0 || num_accounts <= 0 || min_amount < 0 || max_amount < min_amount || total_amount < num_accounts * min_amount) {
|
||||
fprintf(stderr, "Paramètres invalides.\n");
|
||||
fprintf(stderr, "Usage: %s -t total_amount -n num_accounts -m min_amount -M max_amount [-f filename]\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Afficher les paramètres utilisés
|
||||
printf("Génération des comptes avec les paramètres suivants :\n");
|
||||
printf(" Montant total : %d\n", total_amount);
|
||||
printf(" Nombre de comptes : %d\n", num_accounts);
|
||||
printf(" Montant minimum par compte : %d\n", min_amount);
|
||||
printf(" Montant maximum par compte : %d\n", max_amount);
|
||||
printf(" Fichier de sortie : %s\n", filename);
|
||||
|
||||
// Génération des comptes
|
||||
generate_accounts(filename, total_amount, num_accounts, min_amount, max_amount);
|
||||
|
||||
return 0;
|
||||
}
|
13
Secured/Makefile
Normal file
13
Secured/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
# Nom de l'exécutable
|
||||
TARGET = secured_transaction
|
||||
|
||||
# Fichier source
|
||||
SRC = secured_transaction.c
|
||||
|
||||
# Règle par défaut : compilation et lien
|
||||
all:
|
||||
gcc $(SRC) -o $(TARGET)
|
||||
|
||||
# Nettoyage des fichiers générés
|
||||
clean:
|
||||
rm -f $(TARGET)
|
1
Secured/README.md
Normal file
1
Secured/README.md
Normal file
@ -0,0 +1 @@
|
||||
## SOON
|
0
Secured/secured_transaction.c
Normal file
0
Secured/secured_transaction.c
Normal file
13
Unsecured/Makefile
Normal file
13
Unsecured/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
# Nom de l'exécutable
|
||||
TARGET = unsecured_transaction
|
||||
|
||||
# Fichier source
|
||||
SRC = unsecured_transaction.c
|
||||
|
||||
# Règle par défaut : compilation et lien
|
||||
all:
|
||||
gcc $(SRC) -o $(TARGET)
|
||||
|
||||
# Nettoyage des fichiers générés
|
||||
clean:
|
||||
rm -f $(TARGET)
|
31
Unsecured/README.md
Normal file
31
Unsecured/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
@TODO : Améliorer le README.MD (le texte y compris)
|
||||
|
||||
|
||||
# 🏦 Simulateur de Transactions Bancaires Concurrentes
|
||||
|
||||
Ce programme en C simule des transactions bancaires aléatoires entre comptes dans un environnement multi-processus. Il est conçu pour illustrer les défis de la concurrence sans synchronisation explicite.
|
||||
|
||||
## ✨ Fonctionnalités
|
||||
|
||||
- 📖 **Lecture et écriture de comptes** : Les comptes sont stockés dans un fichier avec un format fixe (nom et solde).
|
||||
- 🔄 **Transactions aléatoires** : Effectue des transferts d'argent aléatoires entre comptes.
|
||||
- 🤹 **Simulation multi-processus** : Plusieurs processus enfants effectuent des transactions simultanément.
|
||||
- 📊 **Calcul des soldes** : Affiche le solde total avant et après les transactions.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Limitations et Bugs Potentiels
|
||||
|
||||
🚨 **Ce programme n'utilise pas de mécanismes de verrouillage pour gérer la concurrence.**
|
||||
|
||||
1. **💥 Problème de concurrence** :
|
||||
- Plusieurs processus peuvent lire et écrire dans le fichier en même temps, entraînant des incohérences dans les soldes (race condition).
|
||||
- Par exemple, deux processus modifiant simultanément un compte peuvent écraser leurs changements.
|
||||
|
||||
2. **📉 Corruption des données** :
|
||||
- Une interruption (crash ou arrêt forcé) pendant une transaction peut laisser des données partiellement écrites.
|
||||
|
||||
3. **❌ Absence de validations robustes** :
|
||||
- Aucune vérification supplémentaire pour s'assurer que les montants transférés sont cohérents en cas de concurrence.
|
||||
|
||||
---
|
165
Unsecured/unsecured_transaction.c
Normal file
165
Unsecured/unsecured_transaction.c
Normal file
@ -0,0 +1,165 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ACCOUNT_SIZE 16
|
||||
#define MAX_NAME_LEN 10
|
||||
#define MAX_BALANCE_LEN 5
|
||||
#define FILENAME "../Data/accounts.db"
|
||||
|
||||
// Fonction pour lire un compte dans le fichier
|
||||
void read_account(int fd, int index, char *name, int *balance) {
|
||||
char buffer[ACCOUNT_SIZE];
|
||||
lseek(fd, index * ACCOUNT_SIZE, SEEK_SET);
|
||||
read(fd, buffer, ACCOUNT_SIZE);
|
||||
sscanf(buffer, "%10s %d", name, balance);
|
||||
}
|
||||
|
||||
// Fonction pour écrire un compte dans le fichier
|
||||
void write_account(int fd, int index, const char *name, int balance) {
|
||||
char buffer[ACCOUNT_SIZE];
|
||||
|
||||
// Créer une chaîne formatée avec une largeur fixe
|
||||
snprintf(buffer, ACCOUNT_SIZE - 1, "%-10s%4d", name, balance);
|
||||
|
||||
// Assurer que le buffer termine par '\n'
|
||||
buffer[ACCOUNT_SIZE - 1] = '\n';
|
||||
|
||||
// Positionner et écrire dans le fichier
|
||||
lseek(fd, index * ACCOUNT_SIZE, SEEK_SET);
|
||||
write(fd, buffer, ACCOUNT_SIZE);
|
||||
}
|
||||
|
||||
|
||||
// Fonction pour effectuer une transaction
|
||||
void perform_transaction(int fd, int account_count) {
|
||||
int from_idx = rand() % account_count;
|
||||
int to_idx = rand() % account_count;
|
||||
while (from_idx == to_idx) {
|
||||
to_idx = rand() % account_count;
|
||||
}
|
||||
|
||||
char from_name[MAX_NAME_LEN], to_name[MAX_NAME_LEN];
|
||||
int from_balance, to_balance;
|
||||
|
||||
// Lire les comptes source et destination
|
||||
read_account(fd, from_idx, from_name, &from_balance);
|
||||
read_account(fd, to_idx, to_name, &to_balance);
|
||||
|
||||
// Calculer un montant aléatoire à transférer (max 20% du solde source)
|
||||
int max_transfer = from_balance / 5;
|
||||
if (max_transfer > 0) {
|
||||
int transfer_amount = rand() % max_transfer;
|
||||
|
||||
// Effectuer la transaction
|
||||
from_balance -= transfer_amount;
|
||||
to_balance += transfer_amount;
|
||||
|
||||
// Écrire les nouveaux soldes dans le fichier
|
||||
write_account(fd, from_idx, from_name, from_balance);
|
||||
write_account(fd, to_idx, to_name, to_balance);
|
||||
|
||||
printf("Transaction : %s -> %s : %d€\n", from_name, to_name, transfer_amount);
|
||||
} else {
|
||||
printf("Transaction annulée : Fonds insufisants %s\n", from_name);
|
||||
}
|
||||
}
|
||||
|
||||
// Fonction pour un processus de transactions
|
||||
void process_transactions(int transactions, int account_count) {
|
||||
int fd = open(FILENAME, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("Erreur : Impossible d'ouvrir le fichier");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < transactions; i++) {
|
||||
perform_transaction(fd, account_count);
|
||||
usleep(rand() % 100000); // Temporisation aléatoire
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int calculate_total_balance() {
|
||||
int fd = open(FILENAME, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("Erreur : Impossible d'ouvrir le fichier");
|
||||
return -1;
|
||||
}
|
||||
|
||||
off_t file_size = lseek(fd, 0, SEEK_END);
|
||||
int account_count = file_size / ACCOUNT_SIZE;
|
||||
|
||||
int total_balance = 0;
|
||||
char name[MAX_NAME_LEN];
|
||||
int balance;
|
||||
|
||||
for (int i = 0; i < account_count; i++) {
|
||||
read_account(fd, i, name, &balance);
|
||||
total_balance += balance;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return total_balance;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s <number_of_processes> <transactions_per_process>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int num_processes = atoi(argv[1]);
|
||||
int transactions_per_process = atoi(argv[2]);
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
// Calcul du solde total initial
|
||||
int initial_balance = calculate_total_balance();
|
||||
if (initial_balance < 0) {
|
||||
return 1; // Erreur lors de l'ouverture du fichier
|
||||
}
|
||||
printf("Solde total initial : %d€\n", initial_balance);
|
||||
|
||||
// Ouvrir le fichier pour déterminer le nombre de comptes
|
||||
int fd = open(FILENAME, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("Erreur : Impossible d'ouvrir le fichier");
|
||||
return 1;
|
||||
}
|
||||
off_t file_size = lseek(fd, 0, SEEK_END);
|
||||
close(fd);
|
||||
|
||||
int account_count = file_size / ACCOUNT_SIZE;
|
||||
|
||||
printf("Nombre de comptes : %d\n", account_count);
|
||||
|
||||
// Créer les processus enfants
|
||||
for (int i = 0; i < num_processes; i++) {
|
||||
if (fork() == 0) {
|
||||
process_transactions(transactions_per_process, account_count);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Attendre les processus enfants
|
||||
for (int i = 0; i < num_processes; i++) {
|
||||
wait(NULL);
|
||||
}
|
||||
|
||||
// Calcul du solde total final
|
||||
int final_balance = calculate_total_balance();
|
||||
if (final_balance < 0) {
|
||||
return 1; // Erreur lors de l'ouverture du fichier
|
||||
}
|
||||
printf("Solde total final : %d€\n", final_balance);
|
||||
|
||||
printf("Tout les processus sont terminés !\n");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user