Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

problema server multithread

4 views
Skip to first unread message

Ponch84

unread,
Sep 12, 2009, 1:13:35 PM9/12/09
to
Ciao a tutti ho un problema con un server multithread che deve gestire
un elenco telefonico. Il server risiede su un pc mentre il client (o i
client) su un altro. Inoltre devo gestire dei permessi per
l'inserimento dei numeri oppure per la sola consultazione dell'elenco.
Ora però quando vado a compilare mi dà 2 errori undefined reference to
receiveThread e undefined reference to pthread_create. Come mai?

#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);
}

Lorenzo Beretta

unread,
Sep 13, 2009, 7:17:24 PM9/13/09
to
Ponch84 ha scritto:

> Ciao a tutti ho un problema con un server multithread che deve gestire
> un elenco telefonico. Il server risiede su un pc mentre il client (o i
> client) su un altro. Inoltre devo gestire dei permessi per
> l'inserimento dei numeri oppure per la sola consultazione dell'elenco.
> Ora perᅵ quando vado a compilare mi dᅵ 2 errori undefined reference to

> receiveThread e undefined reference to pthread_create. Come mai?
Perchᅵ gli astri non ti sono favorevoli; se lo fossero, ti avrebbero
ricordato di postare il comando che dai per compilare ;D
Cmq per la pthread_create il motivo ᅵ che devi dirgli di usare la
libreria pthread passando "-lpthread" *dopo* i files da compilare,
tipo "cc (file.c + opzioni varie) ... -lpthread"

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

francesco...@gmail.com

unread,
Sep 14, 2009, 8:31:46 AM9/14/09
to
In effetti è strano, non dovrebbe accettarlo... e così è infatti: dopo
aver aggiustato un paio di cose (tipo aver definito i prototipi delle
funzioni, per evitare warning di compilazione), compilando ottengo:
gcc -Wall -Wextra -lpthread -o prova prova.c
prova.c: In function ‘main’:
prova.c:103: warning: pointer targets in passing argument 3 of
‘accept’ differ in signedness
prova.c: At top level:
prova.c:127: warning: unused parameter ‘param’
/tmp/ccYG9pwt.o: In function `main':
prova.c:(.text+0x2f8): undefined reference to `receiveThread'
collect2: ld returned 1 exit status

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.

Ponch84

unread,
Sep 26, 2009, 4:22:45 PM9/26/09
to
Ma se invece del semaforo gestisco le scritture e le letture tramite
thread non è meglio? Qualcuno può postare una sua soluzione? Please

francesco...@gmail.com

unread,
Sep 28, 2009, 5:36:19 AM9/28/09
to
On 26 Set, 22:22, Ponch84 <ponciare...@gmail.com> wrote:
> Ma se invece del semaforo gestisco le scritture e le letture tramite
> thread non è meglio? Qualcuno può postare una sua soluzione? Please

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.

0 new messages