Mando in esecuzione un client e un server che dovrebbero fare le seguenti cose
Server:
Creazione Socket_S
Accept bloccante su Socket_s
Client:
Crea una sua socket ... chiamiamola Socket_C
tentativo di connettersi alla Socket_S e Invio messaggio
Accept bloccante su Socket_C
Server:
Riceve messaggio estrapola da esso il path per Socket_C
Tenta di connettersi a Socket_C
Invia il messaggio
Client: si risveglia tenta di leggere il messaggio ma si blocca
Ho notato che la accept ritorna 0 (nonostante non ho chiuso stdin), però comunque non da errore cosa a mio parere strana ma la read quando va a leggere da 0 si blocca
Libreria
/** \file comsock.c
* \brief libreria di comunicazione socket AF_UNIX
*
* \author Diego Capasso
*/
#include "comsock.h"
/* -= FUNZIONI =- */
/** Crea una socket AF_UNIX
* \param path pathname della socket
*
* \retval s il file descriptor della socket (s>0)
* \retval -1 in altri casi di errore (setta errno)
* errno = E2BIG se il nome eccede UNIX_PATH_MAX
*
* in caso di errore ripristina la situazione inziale: rimuove eventuali socket create e chiude eventuali file descriptor rimasti aperti
*/
int createServerChannel(char* path)
{
int fd_skt;
struct sockaddr_un sa;
if ( strlen (path) > UNIX_PATH_MAX )
{
errno=E2BIG;
return -1;
}
strncpy(sa.sun_path, path, UNIX_PATH_MAX );
sa.sun_family=AF_UNIX;
fd_skt=socket (AF_UNIX, SOCK_STREAM, 0);
if( fd_skt == -1 )
{
errno= EACCES;
return -1;
}
if ( bind(fd_skt, ((struct sockaddr *) &sa ), sizeof(sa)) != 0 )
{
close ( fd_skt );
return -1;
}
if ( listen( fd_skt, 1 ) != 0 )
{
close ( fd_skt );
return -1;
}
return fd_skt;
}
/** Chiude una socket
* \param s file descriptor della socket
*
* \retval 0 se tutto ok,
* \retval -1 se errore (setta errno)
*/
int closeSocket(int s)
{
return close( s );
}
/** accetta una connessione da parte di un client
* \param s socket su cui ci mettiamo in attesa di accettare la connessione
*
* \retval c il descrittore della socket su cui siamo connessi
* \retval -1 in casi di errore (setta errno)
*/
int acceptConnection(int s)
{
return accept ( s, NULL, 0 );
}
/** legge un messaggio dalla socket --- attenzione si richiede che il messaggio sia adeguatamente spacchettato e trasferito nella struttura msg
* \param sc file descriptor della socket
* \param msg struttura che conterra' il messagio letto
* (deve essere allocata all'esterno della funzione,
* tranne il campo buffer)
*
* \retval lung lunghezza del buffer letto, se OK
* \retval -1 in caso di errore (setta errno)
* errno = ENOTCONN se il peer ha chiuso la connessione
* (non ci sono piu' scrittori sulla socket)
*
*/
int receiveMessage(int sc, message_t * msg)
{
char *buffer;
int n,i;
if ( (n = read( sc , &(msg->type) , sizeof(char)) )== 0 )
{
errno= ENOTCONN;
return -1;
}
else if ( n == -1 )
return -1;
if ( (n = read( sc , &(msg->length), sizeof( unsigned int) ) ) == 0 )
{
errno= ENOTCONN;
return -1;
}
else if ( n == -1 )
return -1;
buffer = malloc(sizeof(char)*msg->length );
if ( ( n = read( sc , buffer, (sizeof(char)*(msg->length)) ) ) == 0 )
{
errno= ENOTCONN;
return -1;
}
else if ( n == -1 )
return -1;
msg->buffer = buffer;
return n;
}
/** scrive un messaggio sulla socket --- attenzione si richiede che il messaggio venga scritto con un'unica write dopo averlo adeguatamente impacchettato
* \param sc file descriptor della socket
* \param msg struttura che contiene il messaggio da scrivere
*
* \retval n il numero di caratteri inviati (se scrittura OK)
* \retval -1 in caso di errore (setta errno)
* errno = ENOTCONN se il peer ha chiuso la connessione
* (non ci sono piu' lettori sulla socket)
*/
int sendMessage(int sc, message_t *msg)
{
void *dest;
int n;
dest=malloc( (sizeof(unsigned int) + sizeof (char) + sizeof (char)*msg->length) );
if(dest==NULL)
{
errno=ENOMEM;
return -1;
}
memcpy( dest, &(msg->type), sizeof(char) );
memcpy( (dest+ sizeof(char)) , &(msg->length), sizeof(unsigned int) );
memcpy( (dest+sizeof(char)+sizeof(unsigned int)) , msg->buffer, (sizeof(char)*(msg->length)) );
if ( ( n = write ( sc, dest, sizeof(unsigned int)+sizeof(char)*(1+msg->length) ) ) == 0 )
{
free ( dest );
return -1;
}
return n;
}
/** crea una connessione all socket del server. In caso di errore funzione tenta NTRIALCONN volte la connessione (a distanza di 1 secondo l'una dall'altra) prima di ritornare errore.
* \param path nome del socket su cui il server accetta le connessioni
*
* \return fd il file descriptor della connessione
* se la connessione ha successo
* \retval -1 in caso di errore (setta errno)
* errno = E2BIG se il nome eccede UNIX_PATH_MAX
*
* in caso di errore ripristina la situazione inziale: rimuove eventuali socket create e chiude eventuali file descriptor rimasti aperti
*/
int openConnection(char* path)
{
int fd_skt,n=0;
struct sockaddr_un sa;
if ( strlen ( path ) > UNIX_PATH_MAX )
{
errno=E2BIG;
return -1;
}
strncpy(sa.sun_path, path, UNIX_PATH_MAX );
sa.sun_family=AF_UNIX;
fd_skt = socket ( AF_UNIX, SOCK_STREAM, 0 );
while ( connect ( fd_skt, (struct sockaddr* ) &sa, sizeof(sa) ) == -1 )
{
if ((errno = ENOENT )&&( n < NTRIALCONN))
{
n++;
sleep (1);
}
else
{
close (fd_skt);
return -1;
}
}
return fd_skt;
}
Server
#include "./lib/dgraph.c"
#include "./lib/comsock.c"
#include "./lib/lista.c"
#include <unistd.h>
#define SOCK_PATH "./tmp/cars.sck"
#define LOG_PATH "./mgcars.log"
#define LONG_USER 30
#define LONG_PWD 30
#define CLEAN {remove(SOCK_PATH);free(msg);fclose(pLog);fclose(pCitta);fclose(pStrade);}
#define CLOSE(when,status) { perror(when);CLEAN;exit(status);}
/* Struttura che verra' passata come parametro agli worker */
typedef struct argomenti
{
/* Dati account */
char *buffer;
int length;
/* Lista account */
list_t lista;
}arg_t;
void * worker_code ( void * argument )
{
arg_t *data = (struct arg_t*) argument;
int i,x=0,y=0;
char *buffer= data->buffer;
char b[3][100];
int cl_skt;
message_t *msg= malloc( sizeof(message_t) );
printf( "Inizio WORKER\n");
for( i=0; i< (data->length); i++)
{
printf("-%c-",buffer[i]);
if( buffer[i] != '\0' )
{
b[x][y]=buffer[i];
y++;
}
else
{
b[x][y]=buffer[i];
y=0;
x++;
}
}
printf("\nUSER_ID:|%s|\nPASSWORD:|%s|\nSOCKET|%s|\n", b[0],b[1],b[2]);
/*switch ( presente( data->lista, b[0], b[1] ) ){
case (-1):
break;
case 1:
data->lista= ins_ord( data->lista, b[0], b[1] );
printf("Account inserito: %d\n",presente( data->lista, b[0], b[1] ) );
default:
break;
}*/
/* Connessione alla socket del client */
for(i=0; i<NTRIALCONN; i++)
{
printf("Tentativo %d connessione a |%s|\n",(i+1),b[2]);
if ( (cl_skt = openConnection(b[2])) != -1 )
{
printf("Mi sono connesso a |%s|\n",b[2]);
break;
}
}
if ( cl_skt == -1 )
{
perror("Apertura socket:");
exit(-1);
}
printf("Connessi alla socket del server: |%s|%d|, PRONTI AL LOGIN\n",b[2],cl_skt);
errno=0;
msg->type='K';
msg->length = strlen("Account confermato");
msg->buffer=malloc(sizeof(char)*msg->length+1);
strcpy(msg->buffer,"Account confermato\0");
if ( sendMessage(cl_skt, msg) == -1 )
perror("SEND NON HA AVUTO SUCCESSO:");
receiveMessage(cl_skt, msg);
printf("|%c|%d|%s|\n",msg->type,msg->length,msg->buffer);
printf("fine del worker server\n");
}
int main ( int argc , char *argv[] )
{
FILE * pCitta, * pStrade, *pLog;
graph_t *grafo;
arg_t argo;
list_t lista=NULL;
int sr_skt;
int x,y,i;
char b[3][100];
message_t *msg;
msg = malloc( sizeof(message_t) );
if( argc != 3 ){
printf("Parametri non corretti, esempio: mgcars file_citta file_strade\n");
exit (-1);
}
if ( ( access( argv[1], R_OK ) ) || ( access ( argv[2], R_OK ) ) ) {
printf("Mancano i permessi di lettura sui file di input\n");
exit (-1);
}
if( (pCitta = fopen ( argv[1] ,"rt")) == NULL )
CLOSE("Apertura file citta:",-1);
if( (pStrade = fopen ( argv [2] , "rt")) == NULL )
CLOSE("Apertura file strade:",-1);
if( (grafo = load_graph (pCitta,pStrade)) == NULL )
CLOSE("Caricamento grafo:",-1);
/* Log File */
if( (pLog = fopen ( LOG_PATH, "rw" )) == NULL )
CLOSE("Apertura file log",-1);
/* Apertura socket Server */
if ( (sr_skt = createServerChannel(SOCK_PATH)) == -1 )
CLOSE("Creazione Socket Server:",-1);
/* Stampa di debug DA ELIMINARE! */ printf("Creata la socket %s\n",SOCK_PATH);
/* Accettazione connessioni */
if( (sr_skt = acceptConnection(sr_skt)) == -1 )
CLOSE("Accettazione connessione su socket risposte:",-1);
/* Ricezione Account */
errno=0;
while(
receiveMessage(sr_skt, msg );
perror("RECIVE");
argo.buffer=msg->buffer;
argo.lista=lista;
argo.length=msg->length;
worker_code ( (void *)&argo );
printf("fine server\n");
}
Client
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "./lib/comsock.c"
#include <pthread.h>
#define SOCK_PATH "./tmp/cars.sck"
#define CLEAN {remove(SOCK_PATH);free(msg);fclose(pLog);fclose(pCitta);fclose(pStrade);}
#define CLOSE(when,status) { perror(when);CLEAN;exit(status);}
/**************************************************************
* Nome: Worker
* Argomenti: Socket
*
* La prima funzione che viene chiamata all'avvio del thread
* che si occupa di rimanere in ascolto sulla socket su cui
* vengono inviate le risposte da parte del client
* ***********************************************************/
void * worker( void * arg )
{
int cl_skt = (int)arg;
message_t *msg;
msg=malloc(sizeof(message_t));
printf("inizio worker client\n");
/* Ascolto connessioni */
if( cl_skt = acceptConnection(cl_skt) == -1 )
{
perror("Accettazione connessione su socket risposte:");
exit(-1);
}
printf("-Accettazione completata-\n");
errno=0;
read( cl_skt , &(msg->type) , sizeof(char));
printf("TYPE---->%c\n",msg->type);
/*
* Ricezione messaggi
while ( errno!=ENOTCONN )
if( receiveMessage( cl_skt, msg ) != -1 )
{
printf( "Risposta: %s\n", msg->buffer );
free(msg->buffer);
}
printf("fine lettura messaggi");
free(msg);
closeSocket(cl_skt);
return NULL;*/
}
int main ( int argc, char * argv[] )
{
char pwd[100];
char *buffer;
char sock_name[100];
int sr_skt,cl_skt,tid,i;
pthread_t ptid;
message_t *msg=malloc(sizeof(message_t));
/* Controllo parametri */
if ( argc != 2 ){
printf("Parametri errati, inserire user_id\n");
exit(-1);
}
printf("$%s: Inserire la password\n",argv[1]);
if ( !(scanf("%s",pwd)) ){
printf("Password troppo corta\n");
exit(-1);
}
/* Creazione Socket_Client */
tid = syscall(SYS_gettid);
sprintf(sock_name,"%d_%s", tid, argv[1] );
if ( (cl_skt = createServerChannel(sock_name)) == -1 )
{
perror("Creazione Socket Client:");
exit(-1);
}
printf("\nCreata la socket |%s|\n",sock_name);
/* Creazione Messaggio di Connessione */
msg->type='C';
msg->length = strlen(argv[1])+strlen(pwd)+strlen(sock_name)+3;
buffer= malloc( sizeof(char)*msg->length );
memcpy( buffer, argv[1], sizeof(char)*(strlen(argv[1])+1) );
memcpy( buffer+(strlen(argv[1])+1), pwd, sizeof(char)*(strlen(pwd)+1) );
memcpy( buffer+(strlen(argv[1])+strlen(pwd)+2), sock_name, sizeof(char)*(strlen(sock_name)+1) );
msg->buffer=buffer;
/* Tentativi connesione al socket del server */
for(i=0; i<NTRIALCONN; i++)
{
if ( (sr_skt = openConnection(SOCK_PATH)) != -1 )
break;
}
if ( sr_skt == -1 )
{
perror("Apertura socket:");
exit(-1);
}
errno=0;
if ( sendMessage(sr_skt, msg) == -1 )
perror("SEND");
printf("Messaggio inviato\n");
/*
if( pthread_create( &ptid, NULL, &(worker), (void *) (cl_skt) ) )
{
perror("Creazione thread Client");
exit(-1);
}
printf("Creato!\n");
if ( pthread_join ( ptid, NULL ) ) {
printf("error joining thread.");
abort();
}
printf("Pthread finito\n");
*/
if( cl_skt = acceptConnection(cl_skt) == -1 )
{
perror("Accettazione connessione su socket risposte:");
exit(-1);
}
printf("-Accettazione completata-\n");
errno=0;
/*
* read( cl_skt , &(msg->type) , sizeof(char));
printf("TYPE---->%c\n",msg->type);
*/
}
So che ci sono tante blasfemie in questo codice a iniziare dai vari include di file.c però sono dei programmini che ho scritto solo per capire dove sbaglio nei due client e server completi
Spero qualcuno mi sappia aiutare Q__Q
Grazie