#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <pthread.h>
#define MAX_DIM 1024
#define CODA 3
#define STRUCTR 32
typedef struct {
char nome[STRUCTR];
char cognome[STRUCTR];
char numero[STRUCTR];
int presenza;
} record;
void*receiveThread(void*param);
int status;
record r;
int ds_sock; // Descrittore della socket
int main() {
int fd; // Descrittore del file
int conn_s; // Descrittore della socket in ascolto
struct sockaddr_in servaddr;
struct sockaddr client;
char buff[MAX_DIM]; // Massima dimensione del buffer lettura
int b; // Integer per la sys call bind
int length;
int chiave_sem; // Identifica il semaforo
int id_sem;
int res;
int proc_id;
pthread_t tid;
void *status;
// Inizio creazione semaforo
chiave_sem=50;
id_sem = semget(chiave_sem,1,IPC_CREAT|IPC_EXCL|0666);
if(id_sem == -1){
id_sem = semget(chiave_sem,1,IPC_CREAT|0666);
semctl(id_sem,IPC_RMID,0); //Pulisco l'ambiente
id_sem = semget(chiave_sem,1,IPC_CREAT|IPC_EXCL|0666);
if(id_sem == -1){
printf("\nErrore nella creazione del semaforo.");
exit(-1);
}
}
// Fine creazione semaforo
res = semctl(id_sem, 0, SETVAL, 1); //inizializzo il semaforo
if(res == -1){
printf("\nErrore nella semctl.");
exit(-1);
}
ds_sock = socket(AF_INET, SOCK_STREAM, 0);
if (ds_sock == -1) exit(0);
else printf("Socket creata con successo!\n");
bzero((char*)&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(2500);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
b = bind(ds_sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(ds_sock, CODA);
if (res == -1) {
printf("Errore nella listen!\n");
exit(-1);
}
signal(SIGCHLD, SIG_IGN);
fd= open("Rubrica.txt", O_CREAT, 0666);
if(fd == -1){
printf("Errore nell'apertura del file\n");
exit(-1);
}
length = sizeof(client);
while(1) {
conn_s = accept(ds_sock, (struct sockaddr*)&client, &length);
res = waitSem(id_sem);
if(res == -1){
printf("Errore nella wait.\n");
exit(-1);
}
if (conn_s == -1) exit(0);
printf("Connessione accettata.\n");
proc_id = pthread_create(&tid,NULL,receiveThread,(void*)&conn_s);
if (proc_id) {
printf("Impossibile creare il thread. Errore: %d\n", proc_id);
exit(-1);
}
}
pthread_join(tid,&status);
if(close(ds_sock)<0){
printf("Errore durante la close.\n");
exit(-1);
}
void*receiveThread(void*param)
{
read(conn_s,buff,MAX_DIM);
while (strcmp(buff, "quit") !=0) {
printf("Valore della password inserito dal client:%s\n", buff);
if (strcmp(buff, "lett") == 0) {
write(conn_s, "plett", MAX_DIM);
leggi_record(conn_s);
}
else if (strcmp(buff, "scri") == 0) {
write(conn_s, "pscrit", MAX_DIM);
scrivi_record(conn_s);
}
else write(conn_s, "errore", MAX_DIM);
read(conn_s,buff,MAX_DIM);
}
close(conn_s);
printf("\nConnessione chiusa.");
res = signalSem(id_sem);
if(res == -1){
printf("\nErrore nella chiamata signal.\n");
exit(-1);
}
return 0;
pthread_exit((void*)&status);
}
}
int leggi_record(int ds) {
int descrittore_file;
int retfile;
int ret;
int risposta;
record pfile;
descrittore_file = open("Rubrica.txt", O_RDONLY);
if (descrittore_file == -1) {
printf("Errore nella lettura del file\n");
exit(-1);
}
ret = read(ds, &r, sizeof(record));
if (ret == -1) {
printf("Errore nella lettura dal client\n");
exit(-1);
}
printf("Nome richiesto: %s\n",r.nome);
printf("Cognome richiesto: %s\n",r.cognome);
do {
retfile = read(descrittore_file, &pfile, sizeof(record));
} while ((retfile!=0)&&(!((strcmp(pfile.nome, r.nome)==0)&&(strcmp
(pfile.cognome, r.cognome)==0))));
if (retfile != 0) {
pfile.presenza = 1;
risposta = write(ds, &pfile, sizeof(record));
if (risposta == -1) {
printf("Errore nell'invio dei dati al client.\n");
exit(-1);
}
else printf("Dati inviati al client.\n");
}
else {
pfile.presenza = 0;
risposta = write(ds, &pfile, sizeof(record));
if (risposta == -1) {
printf("Errore nell'invio dei dati al client.\n");
exit(-1);
}
else printf("Dati inviati al client.\n");
}
close(descrittore_file);
return 0;
}
int scrivi_record(int ds) {
int descrittore_file;
int risp;
descrittore_file = open("Rubrica.txt", O_WRONLY | O_APPEND);
if (descrittore_file == -1) {
printf("Impossibile aprire la rubrica\n");
exit(-1);
}
risp = read(ds, &r, sizeof(record));
if (risp == -1) {
printf("Impossibile ricevere i dati dall'utente\n");
exit(-1);
}
risp = write(descrittore_file, &r, sizeof(record));
r.presenza = 1;
close(descrittore_file);
risp = write(ds, &r, sizeof(record));
if (risp == -1) {
printf("Dati non inviati correttamente\n");
exit(-1);
}
else printf("Dati inviati correttamente\n");
return 0;
}
int waitSem(int sem_id) {
//struct sembuf operazione[1] = {{ numero_semaforo,-1,0}};
struct sembuf oper;
oper.sem_num = 0;
oper.sem_op = -1;
oper.sem_flg = 0;
return semop(sem_id, &oper, 1);
}
int signalSem(int sem_id) {
//struct sembuf operazione[1] = {{ numero_semaforo,+1,0}};
struct sembuf oper;
oper.sem_num = 0;
oper.sem_op = +1;
oper.sem_flg = 0;
return semop(sem_id, &oper, 1);
}
Per la receiveThread, invece, sono curioso e chiedo assistenza anch'io:
il problema ᅵ che in C, a meno che sia cambiato tutto mentre ero
distratto, le definizioni di funzione non si possono annidare, cioᅵ non
puoi definire receiveThread dentro al main e sperare che funzioni; perᅵ
il compilatore sembra accettare quella oscenitᅵ senza problemi, tanto
che se compilo senza linkare mi produce un file .o
Qualcuno mi sa dire perchᅵ mai lo accetta?
gcc -Wall -Wextra etc mi dice "definition shadows previous declaration"
- ma non dovrebbe dare semplicemente errore?
Grazie in anticipo
Quindi molto probabilmente il compilatore prende quel pezzo, vede che
è corretto, ma poi non lo inserisce nella propria tabella dei simboli
e così alla fine lo ignora.
Puoi spiegare meglio cosa intendi dire con la tua prima domanda?
In generale però se hai una risorsa condivisa che deve essere acceduta
in modo sequenziale da tanti thread, piuttosto che usare i semafori,
ti consiglio di usare i mutex (pthread mutex) che sono più semplici da
usare... e a mio parere funzionano anche meglio.
Per quanto riguarda il postare un soluzione.. considera che ci
vorrebbe qualche dettaglio in più su quali sono le specifiche di
questa applicazioncina... ma in generale non puoi pretendere che altri
facciano il programma al posto tuo... primo perché ci vuole un po' di
tempo.
Comunque, in linea generica, ti consiglio di tenere una copia
dell'elenco telefonico in memoria (per la consultazione) e di scrivere
su disco solo quando si inseriscono nuovi elementi. Mi pare di capire
che la modifica di elementi esistenti non è prevista.