PDA

Visualizza la versione completa : [C] Messaging Server in C Posix


skugnizzo78
28-11-2006, 08:33
Per gli esperti del settore :
devo implemntare un MS in C, utilizzando socket TCP e processi.

L'implementazione consiste in due programmi uno relativo al server e l'altro relativo ai client.
I client, dopo l'autenticazione, hanno la possibilità di inviare un messaggio a tutti o ad un client in particolare (Messaggio privato).
Prima di concentrami sulla scrittura del codice sto analizzando su carta le varie problematiche.
Descrivo, spero sia breve, il modello che ho pensato, sperando di ottenere consigli in merito:

il server ad ogni autenticazione crea due figli, uno scrittore (WS) e un lettore (RS).
Altrettanto nel client sono in esecuzione due processi, uno scrittore (WC) e un lettore (RC).
L'utenticazione avviene tramite socket TCP. Il client e il server comunicano tramite questi processi WC->RS e RC<-WS.
Per ogni utente quindi, sono attivi sul server due processi.

1° dubbio : è giusto che per ogni utente siano attivi alcuni processi, o è meglio crearli ogni volta che un utente fa quancle richiesta? Per esempio login->processo per il login->terminazione processo;send ms->processo per il send ms->terminazione processo;....;

Per ogni utente, nel server è presente una coda di messaggi, conteneti i messaggi che dovranno essergli recapitati (Privati e non).

Il processo WS relativo ad un utente è in "ascolto" sulla coda associata ad esso, quando ci sono messaggi, li invia al client.

Il processo RS relativo ad un utente, è in ascolto sul socket, quando arrivano messaggi dal client associato,li pone nelle code dei messaggi degli altri utenti.
Se si tratta di un messaggio privato, lo pone solo nella coda del ricevente, in caso contrario lo pone in tutte le code.
Ogni processo RS, conosce l'id delle code degli altri utenti, grazie ad una strttura resa condivisa.

2° dubbio : considerando che il numero di client sia comunque limitato, non credete che il server sia appesantito dalla presenza di tutte queste attività?
Per ogni utente 2 processi, un socket e una coda di messaggi.

Spero di non avervi annoiato...e sopratutto di ottenere consigli in merito!

billiejoex
28-11-2006, 13:55
- La coda per i messaggi mi pare una buona idea anche perchè essendo un programma di rete è ragionevole pensare che potrebbero intercorrere delle problematiche relative al congestionamento. Puoi anche pensare di inserire un timeout, in tali code, superato il quale il server può decidere arbitrariamente di NON recapitare più il messaggio.
Che poi tu nella realtà fai interagire soltanto una decina di client e questo problema, di fatto, non si pone, è indifferente: imho ti conviene utilizzare sin da subito un approccio 'corretto'.

- Creare due processi sia sul client che sul server non mi pare una cosa ottimale ma non conosco C per cui non mi sbilancio. Secondo me utilizzare un approccio asincrono mediante select sarebbe più sensato e probabilmente anche più performante.
Un'altra possibile soluzione potrebbe essere l'utilizzo di thread multipli o, ancora, un misto tra thread multipli e select per le operazioni di I/O (esempio: lato server crei un nuovo thread per ogni client che si connette, successivamente utilizzi select per leggere/scrivere dal/sul socket).


In questi casi, cmq, anche a me rimangono sempre dubbi se la scelta intrapresa è effettivamente quella più giusta.


Saluti

skugnizzo78
28-11-2006, 14:12
Originariamente inviato da billiejoex
Secondo me utilizzare un approccio asincrono mediante select sarebbe più sensato e probabilmente anche più performante.


Per select cosa intendi?

Grazie per essere intervenuto.

billiejoex
28-11-2006, 14:20
Cerca in uno di questi link:
http://www.google.it/search?hl=it&client=firefox-a&rls=org.mozilla%3Ait%3Aofficial_s&q=select%28%29+Synchronous+I%2FO+Multiplexing&btnG=Cerca&meta=

Viste le tue esigenze (programma di chat) credo ti sia indispensabile.
Qui c'è un esempio di utilizzo che dovrebbe fare al caso tuo:
http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/rzab6/rzab6cmultiplex.htm

Altri esempi credo che si possono trovare su MSDN.

skugnizzo78
28-11-2006, 15:31
Originariamente inviato da billiejoex
Cerca in uno di questi link:
http://www.google.it/search?hl=it&client=firefox-a&rls=org.mozilla%3Ait%3Aofficial_s&q=select%28%29+Synchronous+I%2FO+Multiplexing&btnG=Cerca&meta=

Viste le tue esigenze (programma di chat) credo ti sia indispensabile.
Qui c'è un esempio di utilizzo che dovrebbe fare al caso tuo:
http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/rzab6/rzab6cmultiplex.htm

Altri esempi credo che si possono trovare su MSDN.

Sei stato gentilissimo, ho dato solo uno sguardo, in quanto il progetto è a scopo didattico, e quindi dovrò limitarmi a ciò che è stato spiegato durante il corso (fork,socket,code di mess,shared mem....).
Comunque grazie 1000.

billiejoex
28-11-2006, 15:52
Prego.
Strano cmq che nel corso non abbiano incluso anche select.
La peculiarità di una applicazione del genere (istant messaging) risiede proprio nel fatto che deve essere asincrona, "non bloccante" (in qualunque momento l'applicativo, sia esso client o server, deve poter ricevere o spedire un messaggio), e per fare ciò select è la soluzione adottata il più delle volte.
Puoi anche cavartela senza, beninteso, ma credo si perda in eleganza.
Gli approcci possibili sono cmq diversi e scegliere il più adatto, ripeto, non è proprio banale.
Tieni cmq il thread aggiornato che sono curioso. =)

skugnizzo78
28-11-2006, 17:34
Originariamente inviato da billiejoex
Tieni cmq il thread aggiornato che sono curioso. =)
L'attuale modello prevede :
per ogni richiesta di connessione a buon fine (login) vengono creati :
due processi server (RS - WS), e una coda di messaggi.

RS ha il compito di ricevere i comandi dal client;
WS ha il compito di inviare i messaggi (privati o pubblici) al client.

La comunicazione avviene tramite socket TCP.

WS è in loop sulla coda dei messaggi associata, quando c'è un messaggio lo invia tramite socket al client.

RS è in loop sul socket e interpretando il messaggio sa se si tratta di un messaggio privato o pubblico.
Se è un messaggio pubblico, lo pone in tutte le code relative ai client connessi.
Se è un messaggio privato lo pone solo nella coda relativa al ricevente.
La conoscenza delle code da parte di un processo, è ottenuta tramite una struttura dati aggiornata dai processi ogni volta che una fase di login ha esito positivo.

In questo scenario, la ricezione o l'invio dei messaggi da parte di un client, non blocca la ricezione o l'invio di messaggi relativi ad altri client.

Fammi sapere che ne pensi!

billiejoex
28-11-2006, 17:49
Si, è proprio come pensavo e vale esattamente quanto ho detto sopra:
- creare due processi per le operazioni di I/O a me non pare una soluzione ottimale e ti consiglierei di evitarla salvo caso in cui il prof ti obbliga espressamente ad utilizzarla. Ripeto, cmq, che non conoscendo C questa soluzione potrebbe anche essere sensata se non addirittura preferibile, anche se ne dubito.

- la select, mi ri-ripeto, è fatta apposta per risolvere esattamente il tipo di problematica da te descritta. Sarei lieto di scriverti un codice di esempio ma purtroppo non in C (solo a vedere gli esempi di utilizzo della select in C mi gira la testa).

Loading