Newsgroup: it.comp.os.linux.development
Titolo: Socket

Ciao a tutto il NG, sperando di essere capitato del posto giusto, vorrei sottoporvi un problemi non on le socket (in linux)
PROTOCOLLO TCP
Main Server:
    Socket in ascolto
    fd=Accept() ->controllo richiesta:
        se non valida->close(fd)
        se valida->la passo ad un processo figlio.
	Ho implementato un set di semafori e la shared memory ma non riesco a capire cosa deve fare il figlio, nella shared memory pensavo di inserire l'identificativo della socket privata, ma basta??
	Ogni processo figlio deve gestire fino a 32 socket private aperte in tempi diversi dal padre che è il punto di contatto, ovvero il processo che i client chiamano e che smista le richiste.
	Il Client chiede di aprire uno disco (chiamandolo <DiskName>) possono avvenire varie cose:
a) Non c'è più spazio: ritorno errore al client e chiudo;
b) Esiste già un file con quel nome, ma non ci sono già 32 client che vi accedono: ritorno errore al client;
c) Esiste e ci sono meno di 32 processi: aggiungo la socket privata alla lista per il processo che la gestisce;
d) Non esiste il <DiskName> richiesto (e c'è spazio): lo inserisco nella lista (primo posto) e credo un figlio per la sua gestione;
	I descrittori vengono memorizzati in memoria condivisa... ma a questo 
punto oltre che il descrittore dovrei memorizzare in SHM anche la struttura sockaddr_in associata alle socket private, o no?
-- 
Strahd
per stupire bastan due ore di storia
io cercai di imparare la Treccani a memoria..[F.d.A.]

 che i client chiamano e che smista le richiste.
La soluzione che ho usato io e` stata di creare un processo che sta in 
ascolto, accetta le prime 32 connessioni e poi forka e smette di ascoltare.
Il processo forkato ripete il ciclo (questo si puo` fare visto che il
socket in listen *viene* trasmesso da padre in figlio). Il rischio con
questo sistema e` - col tempo - di avere dei processi che gestiscono 
sempre meno canali...
Ciao,
-- 
       Roberto Divia`             Love at first sight is one of the greatest
       =============             labour-saving devices the world has ever seen.
Mailbox: C02110                 CERN-European Organization for Nuclear Research
E-mail: 
Robert...@cern.ch
           CH-1211 GENEVE 23, Switzerland

 merito...
Forkando il siglio eredita i file descriptor del padre, se ricordo bene dai 
laboratori di sistemi 1.
Guarda la guida alla programmazione di rete di Beej (cerca su google la 
parola "beej" e clicka su "mi sento fortunato").
Dopo l'accept, nel padre chiudi il nuovo socketfd, nel figlio ti limiti ad 
eseguire un ciclo sul nuovo FD e poi terminare con una exit.
Continuo a non capire a cosa ti serva la memoria condivisa nell'esempio 
citato.
-- 
Mox
"Trust the programmer."
"Don't prevent the programmer from doing what needs to be done."
"Keep the language small and simple."
"Provide only one way to do an operation."

 citato.
Penso che l'obiettivo fosse di avere un processo che accetta connessioni per
poi distribuirle a uno o piu' figli che ha forkato in precedenza. La
sequenza temporale e`del tipo:
Padre                     Figlio1          Figlio2
  Listen [*]
  forka Figlio1
                            Parte
  forka Figlio2
                                             Parte
  Accept -> FDa
  Manda FDa a Figlio1
                            Gestisce FDa
  Accept -> FDb
  Manda FDb a Figlio2
                                             Gestisce FDb
[*] La Listen si puo` fare prima o dopo i fork, l'ordine non importa.
In questo schema, la memoria condivisa serviva a gestire un canale
dal Padre al Figlio per il passaggio dei vari FD. Una mailbox...
Questo almeno e` quello che volevo fare io.


 
Esatto
Ed č quello che vorrei fare anche io.
a questo punto perň mi sembra di aver capito che il descrittore sockaddr_it che viene passato alla accept sia la struttura che in qualche modo č riferita dal fd ritornato, quindi.... se memorizzo anche quella in una zona di memoria condivisa dovrei poter leggere il canale....
(ragazzi lo so che se usassi un protocollo datagram (UDP) sarebbe tutto molto piů facile, purtroppo le specifiche richiedono tcp)
-- 
Strhad


 quella in una zona di memoria condivisa dovrei poter leggere il canale....
No. La sockaddr_in il cui puntatore e dimensioni vien passato ad 
accept() viene solo riempita con l'altra meta` del socket (i.e. 
indirizzo e porta del chiamante), ma basta.
Su "Unix Network Programming" di Stevens trovi  ben descritto al punto 
6.10 come passare un file descriptor da un processo all'altro tramite 
sendmsg(), posto che essi siano connessi da un socket in dominio Unix 
(i.e. un socket locale).
Dai anche un'occhiata a questo thread, con un esempio:
http://www.wcug.wwu.edu/lists/netdev/199802/msg00143.html
-- 
   |   \    \  | ___|_  |_  | ianezz a casa sua... :-)
   |  _ \  | \ | _|    /   /  Visita il LinuxTrent a
  _|_/  _\_|  _|____|___|___| 
http://www.linuxtrent.it

 fork.
Ah si, mi era sfuggito. Lui prima crea i processi figli, poi il main smista 
le richieste di connessione ai figli. Avevo interpretato male la 
spiegazione (Strahd, 2 righe in piu' di commenti ci stavano li sopra, dai 
:) ).


 :) ).
Su questo probabilmente hai ragione, ma non è sempre facile essere chiari e al tempo stesso non logorroici.
Volevo evitare di mandare quintali di spiegazioni che poi spesso complicano le cose.
-- 
Strhad


 
http://www.wcug.wwu.edu/lists/netdev/199802/msg00143.html
Ho dato un'occhiata al thread ma sinceramente ho capito poco (sigh!), probabilmente perché non conosco così bene i costrutti C.
Da quello che ho capito però quando si apre una socket (al contrario di un file) vengono memorizzati dei dati in variabili gestite direttaemtne dal sistema.... o sbaglio?
Voglio dire se faccio f=fopen("...") e f è memorizzata in shared memory tutti i processi che vi accedono possono usare f per accedere al file giusto????
Mentre pre le socket non è così.
Per tanto così è più semplice modificare il protocollo
cliente chiama Main che gli da l'ok (altrimenti tanto vale) quindi dice al figlio di contattre lui il cliente....


 giusto????
Purtroppo no. La struttura che conta e` in kernel space, fuori dalla 
portata dei processi. La memoria condivisa e` solo quello: memoria 
condivisa.
fopen() alla fine e` solo un "cappello" sopra open(2).
open(2) a sua volta restituisce semplicemente un numerello che e` un 
indice in una struttura non accessibile al processo e che cambia da 
processo a processo (e quando un processo fa fork(), il figlio si trova 
con una copia che e` uguale a quella del padre, ma da li` in poi 
divergono).
Per cui non puoi sperare di trasferire il numerello e basta da un 
processo all'altro e sperare che funzioni.
Ma siccome e` una cosa desiderabile, allora esiste un meccanismo che e` 
quello a cui ho accennato prima per "trasferire" un file descriptor da 
un processo all'altro, nel senso che un processo spedisce un numerello 
via sendmsg() ad un altro processo tramite un socket dominio Unix, e 
dall'altra parte riemerge un altro numerello (diverso da quello spedito) 
e guardacaso anche la struttura relativa ai file del processo ricevente 
e` cambiata e contiene una nuova voce.


 Ciao,
-- 
cat <<EOF
Paolo Giarrusso, aka Blaisorblade(togliere solo REMOVEONLYTHIS per rispondere)
Kernel 2.4.20 on an i686; Linux registered user n. 292729
EOF

Oppure, se vuoi proseguire [...]
Purtroppo la distinzione è concettuale non è solo per suddividere il carico, altrimenti sarebbe troppo facile
-- 
Strhad


 (i.e. un socket locale).
Bello, mi piace. Sulla mia versione dello Stevens l'ho trovato in
"14.7 Passing Descriptors". UNIX Network Programming Second Edition
(ISBN 0-13-490012-X). Quello che non mi piace e` la "black magic"
(parole testuali) e la dipendenza dalla versione del SO (BSD o SVR4).
Che si debbano fare dei trucchi per gestire la copia non mi va tanto...
Grazie,


 fopen() alla fine e` solo un "cappello" sopra open(2).
  Occhio a non ripetere il mio errore: mescolare chiamate della (2) con
equivalenti chiamate della (3). Il risultato puo' essere un gran
macello (e difficile da riprodurre...).
