Ciao a tutti,
devo fare questo esercizio:
"Creare un server che utilizzi le socket AF_UNIX e più thread concorrenti per gestire un numero di client. Ogni client all'avvio decide quanti messaggi inviare (casualmente). Tutti i messaggi inviati contengono il PID del processo client che li invia. Il srever stampa tutti i messaggi ricevuti sullo standard output.
Il server e' realizzato usando più thread. Un thread dispatcher che accetta le connessioni dai vari client e un thread worker per ogni client. Il thread worker viene attivato appena la connessione si stabilisce e si occupa di leggere i messaggi del client e stamparli sullo stdout. Quando il client termina l'invio (EOF) il thread worker corrispondente termina e libera la memoria occupata."
Il mio problema è che il codice si compila e termina correttamente però l'output non è quello desiderato. È come se ogni processo scriva sulla socket il suo pid un numero indefinito di volte. Posto il codice e alcuni output del programma.
QUESTO È IL CODICE
codice:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <pthread.h>
#define N_MSG_MAX 10
#define N_CLIENT 5
#define SOCK_NAME "./socket"
#define UNIX_PATH_MAX 108
#define N_MAX 50
typedef struct l
{
int FD;
pthread_t PID;
struct l* next;
} list;
/*Prototipi delle funzioni*/
void *thread_disp (void * arg) ;
void *thread_worker (void *arg);
void client ();
int main ()
{
pthread_t TID; /*TID del thread_disp*/
pid_t clients_arr [N_CLIENT]; /*Array con gli indici dei processi client*/
int i=0, err=0;
/*Creo thread_disp*/
if((err=pthread_create (&TID, NULL, &thread_disp, NULL))==-1)
{
errno=err;
perror ("Creating t_disp");
exit (errno);
}
/*Creo i processi client e gli faccio eseguire la funzione client*/
for (i=0;i<N_CLIENT;i++)
{
/*printf ("CREO CLI***\n");*/
if ((clients_arr[i]=fork())==-1)
{
perror ("Creating process");
exit (errno);
}
if (clients_arr[i]==0)
{
printf ("SONO NEL CLIENT\n");
client ();
return 0;
}
}
/*Attendo il completamento del thread_disp e dei processi client*/
pthread_join (TID, NULL);
for (i=0;i<N_CLIENT;i++)
waitpid (clients_arr[i], NULL, 0);
return 0;
}
/*@@@@__FUNZIONE PER THREAD_DISP__@@@@*/
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
void *thread_disp (void *arg)
{
list *L=NULL, *app=NULL; /*Lista di tutti i FD dei socket e dei PID dei relativi thread*/
struct sockaddr_un sa; /*Struttura per l'indirizzo della socket*/
int fd_skt=0; /*File descriptor della socket*/
int i=0;
/*Inizializzo la struttura che contiene l'indirizzo
* del socket per accettare le connessioni*/
strncpy (sa.sun_path, SOCK_NAME, UNIX_PATH_MAX);
sa.sun_family= AF_UNIX;
/*Creo la socket, le assegno un nome e mi metto in ascolto per nuove connessioni*/
if ((fd_skt= socket (AF_UNIX, SOCK_STREAM, 0))==-1)
{
perror ("Creating socket");
exit (errno);
}
if ((bind (fd_skt, (struct sockaddr *) &sa, sizeof (sa)))==-1)
{
perror ("Binding socket");
exit (errno);
}
if ((listen (fd_skt, SOMAXCONN))==-1)
{
perror ("Listening for fd_skt");
exit (errno);
}
/*Per ogni client creo un nuovo elemento della lista che contiene il
file descriptor della socket per quel processo e il pid del thread
che creo per gestire quella connessione.*/
for (i=0;i<N_CLIENT;i++)
{
app=L;
L= (list *) malloc (sizeof(list));
L->next=app;
if ((L->FD= accept (fd_skt, NULL, 0))==-1)
{
perror ("Accepting connection");
exit (errno);
}
if ((L->PID=pthread_create (&(L->PID), NULL, &thread_worker, (void *) L->FD))!=0)
{
errno=L->PID;
perror ("Creating t_worker");
exit (errno);
}
}
/*Attendo la terminazione di tutti i thread_worker*/
app=L;
while (app!=NULL)
{
pthread_join (app->PID, NULL);
close (app->FD);
app=app->next;
}
/*Chiudo il file descriptor della socket e la rimuovo dal file system*/
close (fd_skt);
remove (SOCK_NAME);
return (void *) 0;
}
/*Funzione che esegue ogni client*/
void client ()
{
int FD=0, n=5;
struct sockaddr_un sa;
char buffer [N_MAX];
/*srand (time(NULL));
n=rand () % N_MSG_MAX +1;*/
sprintf (buffer, "%d", getpid());
/*Inizializzo la struttura che contiene l'indirizzo della socket
* per accettare le connessioni e creo la socket per connettermi al server*/
strncpy (sa.sun_path, SOCK_NAME, UNIX_PATH_MAX);
sa.sun_family= AF_UNIX;
FD= socket (AF_UNIX, SOCK_STREAM, 0);
/*Se la connessione va male perché la macchina non è nel network,
* aspetto un secondo e riprovo la connessione*/
while ((connect(FD, (struct sockaddr *) &sa, sizeof (sa)))==-1)
{
if (errno==ENOENT)
sleep (1);
else
exit (errno);
}
/*Scrivo per n volte il pid del processo sulla socket*/
while (n)
{
printf ("%s scrive sulla socket\n", buffer);
if ((write (FD, buffer, N_MAX))==-1)
{
perror ("Writing on socket");
exit (errno);
}
n--;
}
close (FD);
return ;
}
/*Funzione che esegue ogni thread worker di un processo*/
void * thread_worker (void *arg)
{
int FD= (int) arg;
char buffer [N_MAX];
while ((read (FD, buffer, N_MAX))!=-1)
{
printf ("PID-->\t%s\n", buffer);
}
close (FD);
return (void *) 0;
}